一、前言:
我们在前面学习了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的进程间通信也没想象中复杂呢?
喜欢就给我留言哦