为什么';t pipe.close()在python多处理中的pipe.recv()期间导致EOFEROR?

为什么';t pipe.close()在python多处理中的pipe.recv()期间导致EOFEROR?,python,multiprocessing,Python,Multiprocessing,我使用管道和Python的多处理模块在进程之间发送简单对象。文档说明,如果管道已关闭,则调用pipe.recv()将引发EOR。相反,我的程序只是在recv()上阻塞,从未检测到管道已关闭 例如: import multiprocessing as m def fn(pipe): print "recv:", pipe.recv() print "recv:", pipe.recv() if __name__ == '__main__': p1, p2 = m.Pip

我使用管道和Python的多处理模块在进程之间发送简单对象。文档说明,如果管道已关闭,则调用pipe.recv()将引发EOR。相反,我的程序只是在recv()上阻塞,从未检测到管道已关闭

例如:

import multiprocessing as m

def fn(pipe):
    print "recv:", pipe.recv()
    print "recv:", pipe.recv()

if __name__ == '__main__':
    p1, p2 = m.Pipe()
    pr = m.Process(target=fn, args=(p2,))
    pr.start()

    p1.send(1)
    p1.close()  ## should generate EOFError in remote process
输出如下所示:

recv: 1
<blocks here>
recv:1
谁能告诉我我做错了什么?我在Linux和windows/cygwin上有这个问题,但在windows原生Python上没有

分叉(子)进程正在继承其父进程的文件描述符的副本。因此,即使父对象在
p1
上调用“close”,子对象仍然有一个打开的副本,并且底层内核对象没有被释放

要修复此问题,需要关闭子对象中管道的“写入”侧,如下所示:

def fn(pipe):
    p1.close()
    print "recv:", pipe.recv()
    print "recv:", pipe.recv()
从中我观察到,
os.close(pipe.fileno())
可能会立即中断管道,而pipe.close()在所有进程/子进程结束之前不会中断管道。你可以试试看。 警告:不能在之后使用pipe.close(),但pipe.closed仍然返回“false”。所以你可以这样做来更干净:

os.close(pipe.fileno())
pipe=open('/dev/null')
pipe.close()

当然,这是正确的,但问题的目的是确定为什么管道闭合没有在父进程和子进程之间进行通信,就像它在Windows上所做的那样(正如文档所建议的那样)。好的,重新检查后,您完全正确(我没有正确理解您的答案)。直到所有使用文件描述符的进程都关闭了该管道,该管道才被视为“已关闭”。一个有趣/尴尬的结果是,必须将管道的两端发送给子进程,以便它们可以显式关闭其中一个。@Luke:没错。这就是Unix文件描述符的一般行为方式;底层对象保持“打开”,直到引用它的所有描述符都关闭。我无法解释为什么Windows会有不同的行为。那么,为什么孩子会收到父连接的副本,即使它只传入了孩子的连接?这是多处理实现的错误/副作用吗?这方面的记录很差。