Python 2.7.3多处理池挂起

时间:2014-10-16 10:15:58

标签: python multiprocessing

我在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.exitraise SystemExit基本相同,但是应该将此异常委托给其父进程,因此r.get()应该能够正确接收此异常吗?但似乎卡在recv电话上。这是multiprocessing模块中的错误吗?

1 个答案:

答案 0 :(得分:2)

当您致电Pool时,您导致sys.exit()工作进程实际退出。 SystemExit例外是特殊的;当你举起它时,你在退出时提出它的过程。异常不会传播给调用者。因此,这意味着在您的示例中,工作进程根本不会将任何内容返回给父进程。然后父进程将永远等待孩子返回永远不会返回的东西。有关该行为的更深入讨论,请参阅this question

我认为这是一个错误,并且当子进程退出时,pool应该被标记为已损坏,并且所有未完成的任务都应该被中止。这就是concurrent.futures.ProcessPoolExecutor已经表现的方式。我实际上submitted a patch将此行为添加到multiprocessing.Pool,但到目前为止尚未对其进行审核。

现在,回到原来的问题。看起来您希望父进程退出此处,而不仅仅是子进程。要做到这一点,您需要实际将一些对象返回给父对象,然后在接收到该对象时让父对象退出。看起来您已经发现只需提出Exception就可以做到这一点。