Python进程间通信学习笔记
- 更多分享:http://www.catbro.cn
一、前言:
- 我们在前面学习了python的多进程的创建及使用,是不是很Easy呢?
- 但是,一旦涉及到多进程的使用,难免我们就会遇到多进程间通信的问题。
- 本次我们就来学习多进程间的通信,其实也很Easy的哦。
二、Python 进程间通信方式一:Queue
Queue方法介绍
-
1、Queue.qsize():返回当前队列包含的消息数量;
-
2、Queue.empty():判断队列是否为空,空返回True,否则返回False ;
-
3、Queue.full():判断队列是否满了,满返回True,否则返回False;
-
4、Queue.get():取出队列中的一条消息且该消息从列队中移除,可传参超时时长。
-
5、Queue.get_nowait():相当Queue.get(False),取不到值时触发异常:Empty;
-
6、Queue.put():将一个值添加进数列,可传参超时时长。
-
7、Queue.put_nowait():相当于Queue.get(False),当队列满了时报错:Full。
-
示例代码:
from multiprocessing import Queue,Process,Pool; import time,random # 创建列队,不传数字表示列队不限数量 q = Queue() for i in range(10): q.put(i) def run_proc(name): while True: try: p_v = q.get_nowait() print('I am process %s,get value is :%d'%(name,p_v)) time.sleep(random.random()) except Exception as e: print(e); break pool = Pool(3) for i in range(10): pool.apply_async(run_proc,(i,)) pool.close() pool.join()
-
结果输出为:
I am process 0,get value is :0 I am process 3,get value is :1 I am process 4,get value is :2 I am process 4,get value is :3 I am process 0,get value is :4 I am process 3,get value is :5 I am process 4,get value is :6 I am process 3,get value is :7 I am process 3,get value is :8 I am process 4,get value is :9
错误的方法
-
假如我们想让进程往全局的集合中放入数据,是不是可行呢?
-
示例代码:
from multiprocessing import Queue,Process,Pool; import time,random global lst; lst = []; def run_proc(name,v): try: global lst; lst.append(v) print(lst) time.sleep(random.random()) except Exception as e: print(e); pool = Pool(2) for i in range(4): pool.apply_async(run_proc,(i,i,)) pool.close() pool.join() print(lst)
-
输出结果:
[0] [1] [1, 2] [0, 3] []
-
结果说明:子进程结束后,我们发现,lst还是空的,为什么呢?因为每个进程都有属于自己的存储空间,自然全局变量也是进程自己独有的,所以想通过全局变量来实现进程间数据的存储和读取是不可行的,此时我们也可以通过Queue来实现。
-
代码修改如下:
from multiprocessing import Queue,Process,Pool; import time,random q = Queue(); def run_proc(name,v): try: q.put(v) time.sleep(random.random()) except Exception as e: print(e); pool = Pool(2) for i in range(4): pool.apply_async(run_proc,(i,i,)) pool.close() pool.join() v = q.get(); while v is not None: print(v); v = q.get()
-
结果输出如下: 0 1 2 3
-可以发现,通过queue我们就很容易实现进程间数据的存储了。
三、进程间通信方式二:Pipe
-
Pipe管道,可以是单向和双向,默认为双向。双向Pipe允许两端的进即可以发送又可以接受;单向的Pipe只允许前面的端口用于接收,后面的端口用于发送。
-
我们在创建Pipe时传入False即可创建单向管道。
-
示例代码(通过管道,一个进程内发送数据,一个进程内接收数据):
def proc_one(pipe): s = 'Hello,I am proc_one' pipe.send(s) print("proc_one send data is: %s"%s) def proc_two(pipe): while True: print("proc_two recieve data is:", pipe.recv()) if __name__ == "__main__": pipe = Pipe() p1 = Process(target=proc_one, args=(pipe[0],)) p2 = Process(target=proc_two, args=(pipe[1],)) p1.start() p2.start() p1.join() # 限制执行时间描述,不设置则proc_two中会死循环 p2.join(2) print('run end')
-
运行加过为:
proc_one send data is: Hello,I am proc_one proc_two recieve data is: Hello,I am proc_one run end
-
可以看到,我们很容易的就实现了进程间通信。
四、强大的Manage支持管道通信
-
Python中提供了Manage专门用来做数据共享,Manage其支持的数据类型有: Value,Array,list, dict,Queue, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event等
-
示例代码:
def proc_one(lst): s = 'Hello,I am proc_one' lst.append(s); print("proc_one add data is: %s"%s) def proc_two(lst): s = 'Hello,I am proc_two' lst.append(s); print("proc_two add data is: %s" % s) if __name__ == "__main__": m = Manager(); lst = m.list(); p1 = Process(target=proc_one, args=(lst,)) p2 = Process(target=proc_two, args=(lst,)) p1.start() p2.start() p1.join() # 限制执行时间描述,不设置则proc_two中会死循环 p2.join(2) print('run end') print(lst)
-
运行结果为:
proc_one add data is: Hello,I am proc_one proc_two add data is: Hello,I am proc_two run end ['Hello,I am proc_one', 'Hello,I am proc_two']
-
Ok,其它的类型我这就不做演示了,是不是觉得其实Python的进程间通信也没想象中复杂呢?
-
喜欢就给我留言哦