未检测到多处理池中引发的异常 [英] Exception thrown in multiprocessing Pool not detected
问题描述
似乎当从 multiprocessing.Pool 进程引发异常时,没有堆栈跟踪或任何其他指示它已失败.示例:
It seems that when an exception is raised from a multiprocessing.Pool process, there is no stack trace or any other indication that it has failed. Example:
from multiprocessing import Pool
def go():
print(1)
raise Exception()
print(2)
p = Pool()
p.apply_async(go)
p.close()
p.join()
打印 1 并静默停止.有趣的是,引发 BaseException 反而有效.有什么办法可以使所有异常的行为与 BaseException 相同吗?
prints 1 and stops silently. Interestingly, raising a BaseException instead works. Is there any way to make the behavior for all exceptions the same as BaseException?
推荐答案
我有一个合理的解决方案,至少是为了调试目的.我目前没有可以在主进程中引发异常的解决方案.我的第一个想法是使用装饰器,但你只能pickle 在模块的顶层定义的函数,这样就对了.
I have a reasonable solution for the problem, at least for debugging purposes. I do not currently have a solution that will raise the exception back in the main processes. My first thought was to use a decorator, but you can only pickle functions defined at the top level of a module, so that's right out.
取而代之的是一个简单的包装类和一个 Pool 子类,将其用于 apply_async
(因此是 apply
).我将把 map_async
作为练习留给读者.
Instead, a simple wrapping class and a Pool subclass that uses this for apply_async
(and hence apply
). I'll leave map_async
as an exercise for the reader.
import traceback
from multiprocessing.pool import Pool
import multiprocessing
# Shortcut to multiprocessing's logger
def error(msg, *args):
return multiprocessing.get_logger().error(msg, *args)
class LogExceptions(object):
def __init__(self, callable):
self.__callable = callable
def __call__(self, *args, **kwargs):
try:
result = self.__callable(*args, **kwargs)
except Exception as e:
# Here we add some debugging help. If multiprocessing's
# debugging is on, it will arrange to log the traceback
error(traceback.format_exc())
# Re-raise the original exception so the Pool worker can
# clean up
raise
# It was fine, give a normal answer
return result
class LoggingPool(Pool):
def apply_async(self, func, args=(), kwds={}, callback=None):
return Pool.apply_async(self, LogExceptions(func), args, kwds, callback)
def go():
print(1)
raise Exception()
print(2)
multiprocessing.log_to_stderr()
p = LoggingPool(processes=1)
p.apply_async(go)
p.close()
p.join()
这给了我:
1
[ERROR/PoolWorker-1] Traceback (most recent call last):
File "mpdebug.py", line 24, in __call__
result = self.__callable(*args, **kwargs)
File "mpdebug.py", line 44, in go
raise Exception()
Exception
这篇关于未检测到多处理池中引发的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!