进程间的通信——Queue
每个进程中所拥有的数据(包括全局变量)都是独有的,无法与其它进程共享。但大多数进程之间需要进行通信。例如,所有的子进程执行完任务之后,通知处于阻塞状态的主进程继续向下执行。为此,Python的multiprocessing模块中提供了能实现进程间的通信(资源共享)Queue类,该类用于创建和管理存储共享资源的队列,直接采用如下方法创建:
Queue(self, maxsize=-1)
以上方法中,maxsize参数表示队列中数据的最大长度,若该参数小于0或不设置,说明队列可以存储任意个数据,没有长度的限制。
队列的作用类似于数据中转站,可以供多个进程向其内部写入或读取数据,如图1所示。
图1 队列通信的原理
Queue类中提供了put()和get()这两个方法分别向队列中写入数据和从数据中读取并删除数据,关于它们的介绍如下:
1. put()方法
put()方法的声明如下:
Queue.put(item, block=True, timeout=None)
以上声明中,item参数表示向队列中写入的数据;block参数是布尔类型,表示是否阻塞队列;timeout参数表示超时时长,默认为None。若block参数设为True(默认值),表示这是一个阻塞队列,此时若timeout参数设为正值,当队列中装满数据时,队列会阻塞timeout指定的时长,直至该队列中再腾出空间,会在超时后抛出Queue.Full异常;若block参数设为False,表示这是一个非阻塞队列,若队列已满,立即抛出Queue.Full异常。
2. get()方法
get()方法的声明如下:
Queue.get(block=True, timeout=None)
以上声明中,block参数是布尔值,表示是否阻塞队列;timeout参数表示超时时长,默认为None。假设队列中没有数据时,当使用get()方法从队列中读取数据时,若block参数设为True且timeout参数设为正值,则等待timeout指定的时长,直至超出指定的时长后再抛出Queue.Empty异常;若block参数设为False,则会立即抛出Queue.Empty异常。
下面通过队列实现两个进程间的数据共享,具体代码如下:
1 from multiprocessing import Process
2 from multiprocessing import Queue
3 def write(queue):
4 count = 10 # 定义局部变量
5 queue.put(count, block=False) # 将局部变量插入到队列中
6 def read(queue):
7 print(queue.get(block=False)) # 读取队列中的数据
8 if __name__ == '__main__':
9 queue = Queue() # 创建队列,队列的长度没有限制
10 # 创建两个进程分别执行函数work_one和work_other
11 process_one = Process(target=write, args=(queue,))
12 process_another = Process(target=read, args=(queue,))
13 # 启动进程
14 process_one.start()
15 process_another.start()
以上代码的第3~5行定义了一个任务函数work_one(),该函数中用于向队列中插入数据10;第6~7行定义了另一个任务函数work_other(),该函数用于从队列中读取数据;第8~15行是程序的主流程,这些代码首先创建了一个队列queue,然后创建了两个进程分别执行任务函数work_one()和work_other(),最后启动进程。
程序执行的结果如下:
10
由以上结果可知,一个进程成功读取到另一个进程插入到队列中的数据,说明以上程序使用队列实现了两个进程间的通信。