为什么pipe.close()在python多进程的pipe.recv()中不引发EOFError?
我正在使用Python的多进程模块,通过管道在进程之间发送简单的对象。文档上说,如果管道已经关闭,调用pipe.recv()应该会抛出一个EOFError错误。但是,我的程序在调用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>
有没有人能告诉我我哪里做错了?我在Linux和windows/cygwin上都有这个问题,但在Windows的原生Python上却没有。
2 个回答
2
根据这个解决方案,我发现使用os.close(pipe.fileno())
可以立即关闭管道,而使用pipe.close()则需要等所有的进程或子进程结束后才能关闭。你可以试试这个方法。需要注意的是:在使用这个方法后,你不能再用pipe.close(),不过pipe.closed仍然会返回“false”。所以你可以这样做,让代码看起来更整洁:
os.close(pipe.fileno())
pipe=open('/dev/null')
pipe.close()
15
被分叉出来的(子)进程会继承父进程的文件描述符的一个副本。所以即使父进程对p1
调用了“关闭”,子进程仍然有一个副本是打开的,底层的内核对象并没有被释放。
要解决这个问题,你需要在子进程中关闭管道的“写”端,像这样:
def fn(pipe):
p1.close()
print "recv:", pipe.recv()
print "recv:", pipe.recv()