我有multiprocessing.Process
的子流程和multiprocessing.Queue
的队列。
主要流程是使用multiprocessing.Queue.get()
来获取一些新数据。我不想在那里超时,我希望它能够阻止。
但是,当子进程因任何原因死亡(由用户通过kill
手动杀死,或段错误等)时,Queue.get()
将永远挂起。
我该如何避免?
答案 0 :(得分:4)
我认为multiprocessing.Queue
不是我想要的。
我现在正在使用
parent_conn, child_conn = multiprocessing.Pipe(duplex=True)
获取两个multiprocessing.Connection
个对象。然后我os.fork()
或使用multiprocessing.Process
。在孩子身上,我做了:
parent_conn.close()
# read/write on child_conn
在父母(在分叉之后),我做:
child_conn.close()
# read/write on parent_conn
这样,当我在连接上调用recv()
时,当子/父在此时死亡时,它将引发异常(EOFError
)。
请注意,这仅适用于单个孩子。我想Queue
是指你需要多个孩子的时候。在这种情况下,你可能会有一些经理监督所有孩子是否还活着并重新开始。
答案 1 :(得分:1)
Queue
无法知道何时没有任何可能的作家。您可以将对象传递给任意数量的子进程,并且它不知道您是否将它传递给任何给定的子进程。所以它必须等待,即使子进程死了。队列不是一个文件描述符,当孩子死亡时会自动关闭。
您正在寻找的是父母流程中的某种主管,它会注意到孩子意外死亡并以您认为合适的方式处理这种情况。您可以通过捕获SIGCHLD
进程,在线程中检查Process.is_alive
或使用Process.join
来执行此操作。一个简单的实现将使用timeout
调用中的Queue.get
参数,并在返回时执行Process.is_alive
检查。
如果你对子进程的死亡有了更多的控制权,它应该向队列发送一个“EOF”类型的对象(None
,或者它已经完成的某种标记),这样你的父进程可以正确处理它。