各个进程是完全独立的, 肯定需要通信, multiprocessing
包支持进程间通信(IPC, Inter-Process Communication)有两种方式: 管道(Pipe
)和队列(Queue
).
这两种方式都是使用消息传递实现的.
使用Queue
实现IPC
from multiprocessing import Process, Queue
import os, time, random
def write(q):
print("负责写的进程:", os.getpid())
for c in "你好志玲姐姐":
q.put(c) # 向队列中添加数据
time.sleep(random.random()) # 随机休眠
def read(q):
print("负责读的进程:", os.getpid())
while True:
print("读到的数据:", q.get()) # 从队列中读取数据
if __name__ == "__main__":
q = Queue() # 创建一个用于进程间通信的队列
pWrite = Process(target=write, args=(q,)) # 创建写的进程
pRead = Process(target=read, args=(q,)) # 创建读的进程
pWrite.start()
pRead.start()
pWrite.join()
print("负责写的进程结束!")
pRead.terminate() # 因为读的进程内部是死循环, 只能通过这种方式结束
print("所有的进程结束!")
类Queue
Queue
用来进程间通信.
Queue([maxsize])
创建共享的进程队列. maxsize
是允许的最大项目数. 如果省略此参数, 则无大小限制.
Queue
实例对象的一些常用方法:
1. q.close()
关闭队列, 防止向队列中加入更多数据
2. q.empty()
如果调用此方法时q
为空, 则返回True
. 如果有其他进程正在向q
中添加或删除数据,则结果是不可靠的.
3. q.full()
如果q
已满, 则返回True
. 结果也是不可靠的.
4. q.get([block, timeout])
从队列中读取数据. 如果队列为空, 则此方法会阻塞. block
是个布尔值, 用来决定是否阻塞, 默认是True
, 表示为空时阻塞. 如果设置为False
,则在q
为空时抛出异常Queue.Empty
5. q.put(item[, block, timeout)
向队列中添加数据.
6. q.qsize()
返回队列中目前项目的数量. 结果也是不可靠的.
使用pipe
实现IPC
from multiprocessing import Process, Pipe
import os, time, random
def write(p):
print("负责写的进程:", os.getpid())
for c in "你好志玲姐姐":
p.send(c)
time.sleep(random.random())
def read(p):
print("负责读的进程:", os.getpid())
while True:
c = p.recv()
print("接收到的数据", c)
if __name__ == "__main__":
(input_p, output_p) = Pipe() # 创建一个管道, 返回的是一个元组:默认情况下管道是双向的
pWrite = Process(target=write, args=(output_p,)) # 创建写的进程
pRead = Process(target=read, args=(input_p,)) # 创建读的进程
pWrite.start()
pRead.start()
pWrite.join()
print("负责写的进程结束!")
pRead.terminate() # 因为读的进程内部是死循环, 只能通过这种方式结束
print("所有的进程结束!")
类Pipe()
Pipe([duplex])
, 在进程间创建一条管道.
返回一个元组(conn1, conn2)
, 其中conn1, conn2
表示管道两端的Connection
对象. 默认情况下, 管道是双向的.
如果duplex
设置为False
, conn1
值能用于接收, 而conn2
只能用于发送.
Connection
对象具有如下方法:
1. c.close()
关闭连接. 如果c
被垃圾收集, 将自动调用此方法
2. c.poll([timeout])
如果连接上的数据可以用, 返回True
3. c.recv()
接收管道中的数据. 如果连接的另一端已经关闭, 再也不存在任何数据, 将引发EOFError
异常
4. c.send(obj)
通过连接发送数据. obj
是与序列号兼容的任意对象.