victory的博客

长安一片月,万户捣衣声

0%

多线程下载图片

下面的代码是一个网络爬虫程序,可以定期下载图片。这个网络爬虫程序每隔一段时间都会执行一次下载图片任务,在下载任务完成后,休眠一段时间在执行。这样反复执行,知道爬虫程序停止。

示例代码:

# coding=utf-8

import time
import threading
import urllib.request as request

# 线程停止变量
isrunning = True


# 工作线程体函数
def workthread_body():
    while isrunning:
        # 线程开始工作
        print('工作线程执行下载任务...')
        download()
        # 线程休眠
        time.sleep(5)
    print('工作线程结束')


# 控制线程体函数
def controlthread_body():
    global isrunning
    while isrunning:
        # 从键盘输入停止指令exit
        command = input('请输入停止指令')
        if command == 'exit':
            isrunning = False
            print('控制线程结束。')


def download():
    url = 'https://victory-liao.github.io/images/avatar.jpg'
    req = request.Request(url)
    with request.urlopen(req) as response:
        data = response.read()
        f_name = 'download.jpg'
        with open(f_name, 'wb') as f:
            f.write(data)
            print('下载文件成功')


# 主线程
# 创建工作线程对象workthread
workthread = threading.Thread(target=workthread_body)
# 启动线程workthred
workthread.start()

# 创建控制线程对象controlthread
controlthread = threading.Thread(target=controlthread_body)
# 启动线程controlthread
controlthread.start()

线程停止

在线程体结束时,线程就停止了。但在某些业务比较复杂时,会在线程体重执行一个“死循环”。线程体是够执行“死循环”是通过
判断停止变量实现的,“死循环”结束则线程体结束,线程也就结束了。

示例代码:

# coding=utf-8

import time
import threading

# 线程停止变量
isrunning = True


# 工作线程体函数
def workthread_body():
    while isrunning:
        # 线程开始工作
        print('工作线程执行中...')
        # 线程休眠
        time.sleep(5)
    print('工作线程结束。')


# 控制线程体函数
def controlthread_body():
    global isrunning
    while isrunning:
        # 从键盘输入停止指令exit
        command = input('请输入停止指令:')
        if command == 'exit':
            isrunning = False
            print('控制线程结束')


# 主线程
# 创建工作线程对象workthread
workthread = threading.Thread(target=workthread_body)
# 启动线程workthread
workthread.start()

# 创建控制线程对象controlthread
controlthread = threading.Thread(target=controlthread_body)
# 启动线程controlthread
controlthread.start()

等待线程结束

等待线程结束: 一个线程(假设是主线程)需要等待另外一个线程(假设是t1子线程)执行结束才能继续执行。
实现: 通过调用join(timeout=None)方法
参数timeout用来设置超时时间,单位为秒。如果没有设置timeout,则可以一直等待,知道结束。

阅读全文 »

实现线程体的两种方式

实现线程体主要有以下两种方式:
1.自定义函数实现线程体
代码实例:

# coding=utf-8

import threading
import time


# 线程体函数
def thread_body():
    # 当前线程对象
    t = threading.current_thread()
    for n in range(5):
        # 当前线程名
        print('第{0}次执行线程{1}'.format(n, t.name))
        # 线程休眠
        time.sleep(2)
    print('线程{0}执行完成!'.format(t.name))


# 主线程
# 创建线程对象t1
t1 = threading.Thread(target=thread_body)
# 创建线程对象t2
t2 = threading.Thread(target=thread_body, name='MyThread')
# 启动线程t1
t1.start()
# 启动线程t2
t2.start()

2.自定义线程类实现线程体
代码实例:

# coding=utf-8

import time
import threading


class SmallThread(threading.Thread):
    def __init__(self, name=None):
        super().__init__(name=name)

    # 线程体函数
    def run(self):
        # 当前线程对象
        t = threading.current_thread()
        for n in range(5):
            # 当前线程名
            print('第{0}次执行线程{1}'.format(n, t.name))
            # 线程休眠
            time.sleep(2)
        print('线程{0}执行完成'.format(t.name))


# 主线程
# 创建线程对象t1
t1 = SmallThread()  # 通过自定义线程类,创建线程对象
# 创建线程对象t2
t2 = SmallThread(name='MyThread')
# 启动线程t1
t1.start()
# 启动线程t2
t2.start()

使用json提供的loads(str)函数进行JSON数据的解码

函数说明:
str - JSON字符串
返回值 - python数据
示例代码:

# coding=utf-8

import urllib.request
import json

# 使用json模块的loads(str)函数进行JSON数据的解码
url = 'http://localhost:8080/NoteWebService/note.do?action=query&ID=10'

req = urllib.request.Request(url)

with urllib.request.urlopen(req) as response:
    data = response.read()
    json_data = data.decode()
    print("JSON字符串:", json_data)

    py_dict = json.loads(json_data)  # 解码JSON字符串,返回字典
    print('备忘录ID:', py_dict['ID'])
    print('备忘录日期:', py_dict['CDate'])
    print('备忘录内容:', py_dict['Content'])
    print('用户ID:', py_dict['UserID'])

使用urllib.request库从互联网上下载图片

# coding=utf-8

import urllib.request as request

url = 'http://localhost:8080/NoteWebService/logo.png'

with request.urlopen(url) as response:
    data = response.read()
    f_name = 'download.png'
    with open(f_name, 'wb') as f:
        f.write(data)
        print('下载文件成功')

POST请求

使用urllib.request模块可以在python中访问互联网资源,以下是发送POST请求的示例代码。

# coding=utf-8

import urllib.request

url = 'http://localhost:8080/NoteWebService/note.do'

# 准备HTTP参数
params_dict = {'action': 'query', 'ID': '10'}  # 准备将参数放到字典中
params_str = urllib.parse.urlencode(params_dict)  # 将字典参数转换为字符串,形式为action=query&ID=10

# 字符串转换为字节序列对象
params_bytes = params_str.encode()  # 发送POST请求时的参数要以字节序列形式发送

req = urllib.request.Request(url, data=params_bytes)  # 发送POST请求
with urllib.request.urlopen(req) as response:
    data = response.read()
    json_data = data.decode()
    print(json_data)

GET请求

使用urllib.request模块可以在python中访问互联网资源,以下是发送GET请求的示例代码。

# coding=utf-8

import urllib.request

# url中?后的内容是请求参数,多个参数之间以&分割
url = 'http://localhost:8080/NoteWebService/note.do?action=query&ID=10'

# 创建Request对象,默认是GET请求
req = urllib.request.Request(url)

with urllib.request.urlopen(req) as response:
    data = response.read()  # 读取数据,为字节序列数据
    json_data = data.decode()  # 将字节序列数据转换为字符串
    print(json_data)

wxPython控件

1.实现三个文本输入空间和三个静态文本
1.1界面效果

1.2示例代码

class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title="文本输入控件", size=(300, 260))
        panel = wx.Panel(parent=self)
        tc1 = wx.TextCtrl(panel)
        tc2 = wx.TextCtrl(panel, style=wx.TE_PASSWORD)
        tc3 = wx.TextCtrl(panel, style=wx.TE_MULTILINE)

        userid = wx.StaticText(panel, label="用户ID:")
        pwd = wx.StaticText(panel, label="密码:")
        content = wx.StaticText(panel, label="多行文本:")

        # 创建垂直方向的盒子布局管理器对象
        vbox = wx.BoxSizer(wx.VERTICAL)

        # 添加控件到vbox布局管理器
        vbox.Add(userid, flag=wx.EXPAND | wx.LEFT, border=10)
        vbox.Add(tc1, flag=wx.EXPAND | wx.ALL, border=10)
        vbox.Add(pwd, flag=wx.EXPAND | wx.LEFT, border=10)
        vbox.Add(tc2, flag=wx.EXPAND | wx.ALL, border=10)
        vbox.Add(content, flag=wx.EXPAND | wx.LEFT, border=10)
        vbox.Add(tc3, flag=wx.EXPAND | wx.ALL, border=10)

        # 设置面板采用vbox布局管理器
        panel.SetSizer(vbox)

        # 设置tc1初始值
        tc1.SetValue('tony')
        # 获取tc1值
        print('读取用户ID:{0}'.format(tc1.GetValue()))

        tc2.SetValue('123')

        tc3.SetValue('这是一个多行文本!这是一个多行文本!这是一个多行文本!这是一个多行文本!这是一个多行文本!这是一个多行文本!')


app = wx.App()
frm = MyFrame()
frm.Show()
app.MainLoop()
阅读全文 »

布局管理器嵌套

实现效果:
单击Button1按钮,显示“Button1单击”静态文本,单击Button2按钮,显示“Button2单击”静态文本。

示例代码:

布局管理器嵌套

# coding=utf-8
import wx

class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title="布局管理器嵌套", size=(300, 120))
        panel = wx.Panel(parent=self)
        self.static_text = wx.StaticText(parent=panel, label="请单击按钮")
        b1 = wx.Button(parent=panel, id=10, label='Button1')
        b2 = wx.Button(parent=panel, id=11, label='Button2')

        # 创建水平方向的盒子布局管理器hbox对象
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        # 添加b1到hbox布局管理器
        hbox.Add(b1, proportion=1, flag=wx.EXPAND|wx.ALL, border=10)
        hbox.Add(b2, proportion=1, flag=wx.EXPAND|wx.ALL, border=10)

        # 创建垂直方向的盒子布局管理器对象vbox
        vbox = wx.BoxSizer(wx.VERTICAL)
        # 添加静态文本到vbox布局管理器
        vbox.Add(self.static_text, proportion=1, flag=wx.CENTER | wx.FIXED_MINSIZE | wx.TOP, border=10)
        # 将水平hbox布局管理器对象添加到垂直vbox布局管理器对象
        vbox.Add(hbox, proportion=1, flag=wx.CENTER)

        # 设置面板(panel)采用vbox布局管理器
        panel.SetSizer(vbox)

        # 将两个按钮(b1和b2)的单击事件绑定到self.on_click办法
        self.Bind(wx.EVT_BUTTON, self.on_click, id=10, id2=11)

    def on_click(self, event):
        event_id = event.GetId()
        print(event_id)
        if event_id == 10:
            self.static_text.SetLabelText('Button1单击')
        else:
            self.static_text.SetLabelText('Button2单击')


app = wx.App()  # 创建应用程序对象
frm = MyFrame()  # 创建窗口对象
frm.Show()  # 显示窗口
app.MainLoop()  # 进入主事件循环