(一)简介
在现实中,可能有如下需求,多个任务间需要相互配合与联系去实现任务间的数据交流,但是我们知道,进程与进程之间是没有任何联系的,那如何实现呢?这里介绍一种实现进程间的通信的方式---队列Queue。
(二)语法格式
1 from multiprocessing import Process,Queue 2 q = Queue() #创建共享的进程队列 3 q.put(1) # 将一个值放入队列 4 q.put(2) 5 q.put('aaa') 6 print(q.get()) # 返回q中的一个项目 7 8 9 》》》输出: 10 1
说明:
初始化Queue对象时,如果括号内没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限,指导内存尽头。
方法:
- Queue.qsize(): 返回当前队列包含的消息;
- Queue.empty(): 如果队列为空,返回True,反之,返回False;
- Queue.full(): 如果队列满了,返回True,反之False;
- Queue.get([block[, timeout]]):获取队列中的⼀条消息,然后将其从列队中移除,block默认值为True;
1)如果block使⽤默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为⽌, 如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛 出"Queue.Empty"异常;
2)如果block值为False,消息列队如果为空,则会⽴刻抛 出"Queue.Empty"异常;
- Queue.get_nowait():相当Queue.get(False),即不会等待;
- Queue.put(item,[block[, timeout]]):将item消息写⼊队列,block默认值 为True;
1) 如果block使⽤默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写⼊,此时程序将被阻塞(停在写⼊状态),直到从消息列队腾出空间为⽌,如果设置了timeout,则会等待timeout秒,若还没空间,则抛 出"Queue.Full"异常;
2)如果block值为False,消息列队如果没有空间可写⼊,则会⽴刻抛 出"Queue.Full"异常;
- Queue.put_nowait(item):相当Queue.put(item, False),即不会等待;
(三)实例演示:
1 from multiprocessing import Process, Queue 2 import random 3 import time 4 5 6 def write(q): 7 for value in ['A', 'B', 'C']: 8 print('put %s to queue'% value) 9 q.put(value) 10 time.sleep(random.random()) 11 12 13 def read(q): 14 while True: 15 if not q.empty(): 16 value = q.get(True) 17 print('Get %s from queue'% value) 18 time.sleep(random.random()) 19 else: 20 break 21 22 23 if __name__ == '__main__': 24 q = Queue() 25 pw = Process(target=write, args=(q,)) 26 pr = Process(target=read, args=(q,)) 27 28 pw.start() 29 pw.join() 30 31 pr.start() 32 pr.join() 33 34 print('-----结束-----') 35 36 37 》》》输出: 38 put A to queue 39 put B to queue 40 put C to queue 41 Get A from queue 42 Get B from queue 43 Get C from queue 44 -----结束-----
(四)进程池中的Queue
如果要使⽤Pool创建进程,就需要使⽤multiprocessing.Manager()中的 Queue(),⽽不是multiprocessing.Queue(),否则会得到⼀条如下的错误信 息:
RuntimeError: Queue objects should only be shared between processes through inheritance.
只需导入Manager即可:
1 from multiprocessing import Manager, Pool 2 import os 3 4 5 def write(q): 6 print('write启动(%s),其父进程为(%s)' % (os.getpid(), os.getppid())) 7 for i in range(4): 8 print('write写入Queue为%d'%i) 9 q.put(i) 10 11 12 def read(q): 13 print("read启动(%s),其⽗进程为(%s)" % (os.getpid(), os.getppid())) 14 for i in range(q.qsize()): 15 print("reader从Queue获取到消息:%s" % q.get(True)) 16 17 18 if __name__ == '__main__': 19 print("(%s) start" % os.getpid()) 20 q = Manager().Queue() 21 po = Pool() 22 po.apply(write, (q,)) 23 po.apply(read, (q,)) 24 po.close() 25 po.join() 26 print("(%s) End" % os.getpid()) 27 28 29 》》》输出: 30 (25396) start 31 write启动(7448),其父进程为(25396) 32 write写入Queue为0 33 write写入Queue为1 34 write写入Queue为2 35 write写入Queue为3 36 read启动(23796),其⽗进程为(25396) 37 reader从Queue获取到消息:0 38 reader从Queue获取到消息:1 39 reader从Queue获取到消息:2 40 reader从Queue获取到消息:3 41 (25396) End