python multiprocessing模块的Pipe通信问题

易水 发布于 2015/03/22 23:33
阅读 1K+
收藏 0

最近看Python参考手册(第四版)的第20章,进程间通信. 其中有个例子如下


#!/usr/bin/env python
# coding:utf-8

import multiprocessing

def adder(pipe):
    s_p, c_p = pipe
    c_p.close()
    while True:
        try:
            x, y = s_p.recv()
        except EOFError:
            break
        result = x + y
        s_p.send(result)
    print "Server done"

if __name__ == '__main__':
    (server_p, client_p) = multiprocessing.Pipe()

    # 启动服务器进程
    adder_p = multiprocessing.Process(
        target=adder, args=((server_p, client_p),))
    adder_p.start()

    # 关闭客户端中的服务器管道
    server_p.close()

    # 在服务器上提出一些请求
    client_p.send((3, 4))
    print client_p.recv()

    client_p.send(('Hello', 'World'))
    print client_p.recv()

    # 完成,关闭管道
    client_p.close()

    # 等待消费者进程关闭
    adder_p.join()



运行结果是:



7
HelloWorld
Server done


那么问题来了:

adder这个函数中的管道pipe的一端c_p已经关闭了,另外一端s_p仍然可以接收到数据,这个可以理解,但是s_p还可以发送就不理解了,网上搜了好多资料好像都没介绍这个

下面是在python解析器里面模拟上面那个情况,在管道pipe的c_p端先发送2个数据过去,然后关闭c端,另外一端s可以收到前面发过来的2个数据,如果再接收就抛出异常了.而且s端这个时候也是无法发送数据的.不知道为什么上面手册给的例子里面管道c_p端关闭之后,另外一端s_p还可以发送数据出去?


>>> from multiprocessing import Pipe
>>> s, c = Pipe()
>>> c.send(1)
>>> c.send(2)
>>> c.close()
>>> s.recv()
1
>>> s.recv()
2
>>> s.recv()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
EOFError
>>> s.send(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 232]
>>>







加载中
0
s
shadow_panda

multiprocessing.Pipe()创建的管道实例,默认是全双工模式工作的,即两端即可以发送数据,也可以接收数据。

0
小小仓鼠
小小仓鼠

是这样的,当adder_start的时候,我们就创建了一个新的进程,主进程和子进程分别有自己的一对管道,和一般的两个进程不同的是,这两对管道有一定的联系。在第二个例子中,我们在同一个进程内有两对管道(其实是一对管道,因为Python 的赋值操作,其实质是创建了一对管道,但有两个不同的变量指向了这个管道,我们通过一个变量把管道的一个端口关闭了,这个端口就关闭了,就像可变数据结构列表一样,“a=[1,2,3],b=a,b.append(4),a也变了”);在第一个例子中,因为是两个不同的进程,这两对管道是真实存在的两对管道,有点儿像冗余策略,允许其中一个管道的一个端点关闭(或一个进程下关闭一个端点),不影响通信,但相同进程下的端点不能都关闭。最后,关于第一个例子,有可能不是多进程的原因,而是与函数的命名空间有关(不知道该怎么判断)

0
易水
易水

3Q, 用id(s_p) 看了下, id确实不一样

返回顶部
顶部