原文地址,本文在原文基础上添加了部分注释。
multiprocessing.Pipe([duplex]) 方法返回2个连接对象(conn1, conn2),代表管道的两端,默认duplex为True,是双向通信。如果duplex为False,则conn1只能用来接收消息,conn2只能用来发送消息。
实例如下:
#!/usr/bin/python
#coding=utf-8
import os
from multiprocessing import Process, Pipe
def send(pipe):
pipe.send(['spam'] + [42, 'egg'])
pipe.close()
def talk(pipe):
pipe.send(dict(name = 'Bob', spam = 42))
reply = pipe.recv()
print('talker got:', reply)
if __name__ == '__main__':
(con1, con2) = Pipe() #Pipe()构造器直接返回一对连接对象,这两个对象之间可以首发内容
sender = Process(target = send, name = 'send', args = (con1, ))
sender.start()
print("con2 got: %s" % con2.recv())#从send收到消息
con2.close()
(parentEnd, childEnd) = Pipe()
child = Process(target = talk, name = 'talk', args = (childEnd,))
child.start()
print('parent got:', parentEnd.recv())
parentEnd.send({x * 2 for x in 'spam'})
child.join()
print('parent exit')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
输出如下:
con2 got: ['spam', 42, 'egg']
('parent got:', {'name': 'Bob', 'spam': 42})
('talker got:', set(['ss', 'aa', 'pp', 'mm']))
parent exit
代码中send方法是利用管道发送一个列表,列表内容为['spam',42,'egg'],而代码talk是利用管道发送一个字典,再接收一个内容,接收的内容来自与之配对的另一个管道。示例代码中会分别测试send方法和talk方法。
示例代码16至20行是用来测试send方法的。使用管道是进行跨进程通信,因此第17行代码中启动一个进程,在该进程中运行send方法,在send方法中用管道con1来发送列表,在主进程中用与con1配对的con2来接收内容,并将接收到的内容打印到控制台。从而完成了send进程去主进程之间内容的传递。
22至28行用来测试talk方法,两个管道都进行了消息的收和发。第23行创建了单独的talk进程并启动,在talk进程中运行talk方法,即利用childEnd管道发送一个字典,随后childEnd管道进入一个接收状态,一直等待与childEnd配对的parentEnd管道发送的内容。第25行,在主进程中,parentEnd管道接收到childEnd管道发送的内容,然后parentEnd将收到的内容做一个简单的处理后进行发送,此时发送的内容会被talk进程的childEnd管道的recv接收到并在talk进程是talk方法中进行打印。随后talk方法执行完毕,talk进程执行完毕。
如果将第26行代码注释掉,则主进程和talk进程都会被卡住。这是因为,第27行的child.join()方法决定了主进程必须等待talk进程执行完毕(并将其关闭)后才可以执行执行。但是此时talk进程会卡在第12行一直等到parentEnd发送内容过来,不然会一直等待。如果一直等待的话,talk线程并不会结束,talk不结束主进程也会卡在第27行不能往下执行。