Python 2.7.3 多进程池挂起
我在ipython中有一段代码,子进程尝试执行 sys.exit(...)
,结果导致父进程卡住了。这算不算一个bug呢?有没有什么解决办法?
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
模块的bug吗?
1 个回答
2
你在调用 sys.exit()
时,让 Pool
的工作进程直接退出了。SystemExit
这个异常是特别处理的;当你抛出它时,抛出它的进程就会退出。这个异常不会传递给调用它的地方。所以在你的例子中,工作进程根本没有把任何东西返回给父进程。结果,父进程就会一直等待子进程返回一些永远不会返回的东西。想了解更多这种行为,可以看看 这个问题。
我认为这是一个bug,当子进程退出时,pool
应该被标记为坏掉了,所有未完成的任务应该被终止。这就是 concurrent.futures.ProcessPoolExecutor
的行为。我实际上已经 提交了一个补丁,希望把这种行为添加到 multiprocessing.Pool
中,但到现在为止还没有被审核。
回到你最初的问题。看起来你想让 父进程 也退出,而不仅仅是子进程。要做到这一点,你需要把某个对象返回给父进程,然后在父进程收到这个对象时让它退出。看起来你发现可以通过简单地抛出一个 Exception
来实现这一点。