Python多处理:子进程崩溃?

Python多处理:子进程崩溃?,python,multiprocessing,Python,Multiprocessing,当python脚本打开子进程而一个进程崩溃时会发生什么 主进程会崩溃吗 其他子流程会崩溃吗 是否存在传播的信号或其他事件 使用多处理.Pool时,如果池中的一个子进程崩溃,您将不会收到任何通知,并且将立即启动一个新进程来代替它: >>> import multiprocessing >>> p = multiprocessing.Pool() >>> p._processes 4 >>> p._pool [<Proc

当python脚本打开子进程而一个进程崩溃时会发生什么

主进程会崩溃吗

其他子流程会崩溃吗


是否存在传播的信号或其他事件

使用
多处理.Pool
时,如果池中的一个子进程崩溃,您将不会收到任何通知,并且将立即启动一个新进程来代替它:

>>> import multiprocessing
>>> p = multiprocessing.Pool()
>>> p._processes
4
>>> p._pool
[<Process(PoolWorker-1, started daemon)>, <Process(PoolWorker-2, started daemon)>, <Process(PoolWorker-3, started daemon)>, <Process(PoolWorker-4, started daemon)>]
>>> [proc.pid for proc in p._pool]
[30760, 30761, 30762, 30763]
回到游泳池:

>>> [proc.pid for proc in p._pool]
[30760, 30761, 30762, 30767]  # New pid for the last process
您可以继续使用池,就好像什么都没有发生一样。但是,被终止的子进程在其终止时正在运行的任何工作项都不会被完成或重新启动。如果您正在运行依赖于该工作项完成的阻塞
map
apply
调用,则该调用可能会无限期挂起。存在问题,但该问题仅在中修复,而不是在
多处理.Pool
中修复。从Python3.3开始,
ProcessPoolExecutor
将在终止子进程时引发
BrokerProcessPool
异常,并禁止进一步使用该池。遗憾的是,
多处理
没有得到这种增强。现在,如果您想防止子进程崩溃导致池调用永久阻塞,那么必须使用

注意:以上仅适用于池中实际崩溃的进程,这意味着该进程完全死亡。如果子流程引发异常,则当您尝试检索工作项的结果时,该异常将向上传播到父流程:

>>> def f(): raise Exception("Oh no")
... 
>>> pool = multiprocessing.Pool()
>>> result = pool.apply_async(f)
>>> result.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 528, in get
    raise self._value
Exception: Oh no
如果引发异常,则行为类似:

from multiprocessing import Process

def f(x):
    raise Exception("Oh no")

if __name__ == '__main__':
    p = Process(target=f)
    p.start()
    p.join()
    print(p.exitcode)
    print("done")
输出:

Process Process-1:
Traceback (most recent call last):
  File "/usr/lib/python3.2/multiprocessing/process.py", line 267, in _bootstrap
    self.run()
  File "/usr/lib/python3.2/multiprocessing/process.py", line 116, in run
    self._target(*self._args, **self._kwargs)
TypeError: f() takes exactly 1 argument (0 given)
1
done

如您所见,子进程的回溯是打印出来的,但它不会影响主进程的执行,主进程能够显示子进程的
exitcode
1

看起来bug仍然存在,并且有一些未完成的修复尝试,最近的一个是
from multiprocessing import Process

def f(x):
    raise Exception("Oh no")

if __name__ == '__main__':
    p = Process(target=f)
    p.start()
    p.join()
    print(p.exitcode)
    print("done")
Process Process-1:
Traceback (most recent call last):
  File "/usr/lib/python3.2/multiprocessing/process.py", line 267, in _bootstrap
    self.run()
  File "/usr/lib/python3.2/multiprocessing/process.py", line 116, in run
    self._target(*self._args, **self._kwargs)
TypeError: f() takes exactly 1 argument (0 given)
1
done