注1: 我想在多个进程中使用mutiprocessing.Queue,当我发现这个问题发生在单进程情况下。因此,以下代码使用单个过程来简化问题。
有一个类似的问题:Broken pipe error with multiprocessing.Queue。
该帖子的答案证明了这个问题是因为主线程在队列线程完成其工作之前退出。他修复它的方法是在代码中添加sleep(0.1)
:
import multiprocessing
import time
def main():
q = multiprocessing.Queue()
for i in range(10):
print i
q.put(i)
time.sleep(0.1) # Just enough to let the Queue finish
if __name__ == "__main__":
main()
但是,我认为睡眠不是生产代码的稳定方法,所以我尝试使用join
来做到这一点。你可以在下面看到我的代码,但不幸的是,它不起作用。是否有人知道如何在不睡觉的情况下做到这一点?
import multiprocessing
import time
def main():
q = multiprocessing.Queue()
for i in range(10):
q.put(i)
# time.sleep(4)
q.close()
q.join_thread()
if __name__ == "__main__":
main()
答案 0 :(得分:0)
让我们先描述multiprocessing.Queue
的一些细节。
当一个对象被放入队列时,该对象被腌制并且后台线程以后将该pickle数据刷新到底层管道。
管道是通过reader, writer = socket.socketpair()
创建的。
queue.close()
专为多进程而设计,它可以完成两件事
reader
(重要!)sentinel
值发送给后台线程queue.buffer
如果遇到这样的价值会退出在单个流程的情况下,queue.close()
不起作用的原因是因为第1步,如果buffer
中仍有一些数据,后台线程将继续写入数据到已经关闭的套接字,导致Broken pipe
错误。
演示错误的简单示例
import socket
reader, writer = socket.socketpair()
writer.send("1")
# queue.close() will internally call reader.close()
reader.close()
# got a Broken pipe error
writer.send("2")
在多进程的情况下,在主进程中关闭reader
只会减少底层套接字的引用计数(主进程和子进程共享套接字),而不是真正关闭(或关闭)套接字。