多进程之间的常用通信方法有两种,及Queue和Pipe
一、Queue
Queue([maxsize]):创建共享的进程队列。maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。底层队列使用管道和锁定实现。另外,还需要运行支持线程以便队列中的数据传输到底层管道中。
Queue的实例q具有以下方法:
q.get( [ block [ ,timeout ] ] ):返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有项目可用为止。block用于控制阻塞行为,默认为True. 如果设置为False,将引发Queue.Empty异常(定义在Queue模块中)。timeout是可选超时时间,用在阻塞模式中。如果在制定的时间间隔内没有项目变为可用,将引发Queue.Empty异常。
q.get_nowait() :同q.get(False)方法。
q.put(item [, block [,timeout ] ] ) :将item放入队列。如果队列已满,此方法将阻塞至有空间可用为止。block控制阻塞行为,默认为True。如果设置为False,将引发Queue.Empty异常(定义在Queue库模块中)。timeout指定在阻塞模式中等待可用空间的时间长短。超时后将引发Queue.Full异常。
q.qsize() :返回队列中目前项目的正确数量。此函数的结果并不可靠,因为在返回结果和在稍后程序中使用结果之间,队列中可能添加或删除了项目。在某些系统上,此方法可能引发NotImplementedError异常。
q.empty() :如果调用此方法时 q为空,返回True。如果其他进程或线程正在往队列中添加项目,结果是不可靠的。也就是说,在返回和使用结果之间,队列中可能已经加入新的项目。
q.full() :如果q已满,返回为True. 由于线程的存在,结果也可能是不可靠的(参考q.empty()方法)。
就比如,进程1所得到的结果,要在进程2、3、4等进程当中用,此时,可以通过Queue,让其他进程来获得进程1中的结果。
现在,我们有一个场景,在一个进程当中,计算出两个数的和,然后在另外一个进程中使用第一个进程中计算的结果,除以2,即得到这两个数的平均值,代码如下:
from multiprocessing import Process,Queue
class AddProc(Process):
def __init__(self,q,number1,number2):
super(AddProc, self).__init__()
self.number1 = number1
self.number2 = number2
self.q=q
def run(self):
res = self.number1 + self.number2
self.q.put(res)
print("相加进程1:",res)
class DiviSion(Process):
def __init__(self,q):
super(DiviSion, self).__init__()
self.q = q
def run(self):
res = self.q.get()/2
print("除2进程2:",res)
if __name__ == '__main__':
print("主进程开始")
q = Queue()
p1 = AddProc(q,12,13)
p2 = DiviSion(q)
p1.start()
p2.start()
p1.join()
p2.join()
print("主进程结束!")
二、Pipe
管道通信,就是各个进程之间相互通信,有双工和半双工两种方式,默认为双工通信
同样,拿上面的案例,改用管道通信改写,就变成下面这个样子:
from multiprocessing import Process,Pipe
class AddProc(Process):
def __init__(self,pi1,number1,number2):
super(AddProc, self).__init__()
self.number1 = number1
self.number2 = number2
self.pi1=pi1
def run(self):
res = self.number1 + self.number2
self.pi1.send(res)
print("相加进程1:",res)
class DiviSion(Process):
def __init__(self,pi2):
super(DiviSion, self).__init__()
self.pi2 = pi2
def run(self):
res = self.pi2.recv()/2
print("除2进程2:",res)
if __name__ == '__main__':
pi1,pi2=Pipe()
print("主进程开始")
p1 = AddProc(pi1,12,13)
p2 = DiviSion(pi2)
p1.start()
p2.start()
p1.join()
p2.join()
print("主进程结束!")
p1,p2=Pipe():Pipe创建之后得到管道的两端
self.pi1.send() :write进程负责把数据通过管道发送给另一个进程
self.pi2.recv():当管道中没有数据,该行代码一直阻塞
recv函数是阻塞函数