之前我们做的自动化工具,每当开始处理数据,GUI(图形界面)就会变成无响应了,用户体验很不好。
这次,我们来给工具加上多线程,让它在处理数据的同时,GUI也能进行交互。
首先,带大家简单了解下,什么是线程、进程和协程。大家看看下面代码的执行逻辑:
import time
count = 0 # 执行任务次数为0
def down_file():# 定义一个下载文件的函数
time.sleep(10) # 等待10秒
count += 1 #执行任务次数加1
print("finish!") # 下载完成
def wait_a_minute(): # 定义一个会等待数秒的函数
time.sleep(5) # 等待5秒
count += 1 #执行任务次数加1
print("ok!")
down_file()
wait_a_minute()
print(count) # 打印执行任务次数
一般来说,程序有一个进程,进程里有一个线程。由于我们只有一个线程,没办法同时执行两段代码,所以只能一个一个执行函数。按顺序执行完程序,用时15秒。
有没有什么办法能提高效率呢?
有,我们可以用多线程。给程序再加一个线程,主线程执行上面的函数,子线程执行下面的函数,用时10秒,执行完后打印count,值为2。(注意:如果两个线程同时对count进行运算,结果会出错。有需要时可以给count(临界资源)家一个锁,得到钥匙的线程才能执行,执行完后释放钥匙,让下一个线程获得钥匙。)
我们还可以用多进程。主进程执行上面的函数,子进程执行下面的函数,用时10秒。执行完后打印count,你可能认为值为2,但值却是1。count明明加了两次,可是为什么值却是1呢?所有线程共享一块内存空间,可以共享所有变量,但所有进程都有各自的内存空间,两个进程都有各自的count变量,所以需要在进程间建立通信。
我们还可以用协程。协程只有一个进程,一个线程,它只能同时执行一段代码,但是,它在执行到下载任务时,会让系统继续下载,自己却跑到其他代码上继续执行。等下载完成,它才回到之前的地方往下执行。
好了,以上是对线程、进程、协程的粗浅介绍。我是以使用为导向的,很多用法都没讲,推荐大家看一下廖雪峰的教程的相关章节。
我们思考一下,为什么我们之前写的带GUI的应用,在处理数据时会无响应呢?
对了,因为只有一个线程,无法同时执行GUI的代码和数据处理的代码。
以下是改造成多线程前的代码:
class demo():
def __init__(self):
# 省略一万行
self.bo_deal = tk.Button(window, text='处理文件', command=self.deal_files)
# 省略一万行
def deal_files(self):
print("正在处理数据")
print("数据处理完成")
改造一下代码:
from threading import Thread #引入库
class demo():
def __init__(self):
# 省略一万行
self.bo_deal = tk.Button(window, text='处理文件', command=self.deal_files)
# 省略一万行
def deal_files(self):
def run():
print("正在处理数据")
print("数据处理完成")
t = Thread(target=run) # 创建线程。如需传入参数,可用args参数,例args=(1,2,3)
t.start() # 启动线程
t.join() # 等线程执行完毕后,才往下执行
好了,你已经知道如何做了,那就马上打开电脑,改造你的程序吧!
逃离重复性工作,留出时间提升自己!