我對這個問題的合理解決,至少在調試的目的。目前我還沒有一個解決方案可以在主流程中引發異常。我的第一個想法是使用裝飾,但你只能醃functions defined at the top level of a module,所以這是正確的。
取而代之的是一個簡單的包裝類和一個Pool子類,它使用apply_async
(因此爲apply
)。我將離開map_async
作爲讀者的練習。
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
我有同樣的問題。原因如下:工作進程捕獲異常並在結果隊列中放置失敗代碼和異常。回到主進程中,Pool的結果處理線程獲取失敗代碼並忽略它。某種猴子補丁調試模式可能是可能的。另一種方法是確保你的工作者函數捕獲任何異常,返回它併爲你的處理器打印一個錯誤代碼。 –
這已經在這裏回答:http://stackoverflow.com/a/26096355/512111 – j08lue