我有一个合理的解决方案,至少用于调试目的。我目前没有一个可以在主要流程中引发异常的解决方案。我的第一个想法是使用装饰器,但是您只能腌制在模块顶层定义的函数,所以没错。
取而代之的是一个简单的包装类和一个Pool子类,将其用于apply_async
(因此apply
)。我将map_async
作为练习留给读者。
import traceback
from multiprocessing.pool import Pool
import multiprocessing
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:
error(traceback.format_exc())
raise
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