Part 4.系统编程之进程---进程间通信

(一)简介

在现实中,可能有如下需求,多个任务间需要相互配合与联系去实现任务间的数据交流,但是我们知道,进程与进程之间是没有任何联系的,那如何实现呢?这里介绍一种实现进程间的通信的方式---队列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

 

posted @ 2018-10-04 11:42  A-handsome-cxy  阅读(106)  评论(0编辑  收藏  举报