我在ipython中有以下代码,其中子进程尝试执行sys.exit(...)
但导致父进程挂起。这是一个错误吗?知道如何解决这个问题吗?
In [1]: from multiprocessing import Pool
In [2]: def f():
...: import sys
...: sys.exit('exiting system...')
...:
In [3]: p = Pool(processes=2)
In [4]: r = p.apply_async(f, [])
In [5]: r.get() <---- it is hanging here forever.
我还尝试将raise SystemExit(...)
代替sys.exit(...)
,但这是相同的。我知道的唯一解决方法是将raise Exception(...)
放在合适的位置。
我理解sys.exit
与raise SystemExit
基本相同,但是应该将此异常委托给其父进程,因此r.get()
应该能够正确接收此异常吗?但似乎卡在recv
电话上。这是multiprocessing
模块中的错误吗?
答案 0 :(得分:2)
当您致电Pool
时,您导致sys.exit()
工作进程实际退出。 SystemExit
例外是特殊的;当你举起它时,你在退出时提出它的过程。异常不会传播给调用者。因此,这意味着在您的示例中,工作进程根本不会将任何内容返回给父进程。然后父进程将永远等待孩子返回永远不会返回的东西。有关该行为的更深入讨论,请参阅this question。
我认为这是一个错误,并且当子进程退出时,pool
应该被标记为已损坏,并且所有未完成的任务都应该被中止。这就是concurrent.futures.ProcessPoolExecutor
已经表现的方式。我实际上submitted a patch将此行为添加到multiprocessing.Pool
,但到目前为止尚未对其进行审核。
现在,回到原来的问题。看起来您希望父进程退出此处,而不仅仅是子进程。要做到这一点,您需要实际将一些对象返回给父对象,然后在接收到该对象时让父对象退出。看起来您已经发现只需提出Exception
就可以做到这一点。