之前我们做的自动化工具,每当开始处理数据,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() # 等线程执行完毕后,才往下执行

好了,你已经知道如何做了,那就马上打开电脑,改造你的程序吧!

逃离重复性工作,留出时间提升自己!