我想知道在通过多处理模块执行的函数内部存在异常时获取堆栈跟踪的最佳方法。这是一个例子:
import multiprocessing
def square(x):
raise Exception("Crash.")
return x**2
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=4)
results = pool.map_async(square, range(5))
for result in results.get():
print result
打印:
Traceback (most recent call last):
File "/extra/workspace/Playground/src/multiproc/multiproc_debug.py", line 11, in <module>
for result in results.get():
File "/extra/Python 2.6/lib/python2.6/multiprocessing/pool.py", line 422, in get
raise self._value
Exception: Crash.
所以没有有用的堆栈跟踪,这非常烦人。我目前的解决方案是:
import multiprocessing
import traceback
def square(x):
try:
# some more code...
raise Exception("Crash.")
except Exception, exception:
print exception
traceback.print_exc()
raise
return x**2
有没有办法在没有所有样板代码的情况下获得此行为?如果没有,那么不包括此功能的原因是什么?
编辑:可以使用装饰器作为样板代码,但我不知道标准库中是否包含这样的装饰器?
答案 0 :(得分:11)
看起来您应该避免从主函数中引发异常。相反,您可以捕获它,将其视为返回主程序的值,然后将其提升到那里。 Re-throwing exceptions in Python有更多详情。
答案 1 :(得分:4)
在Python 3.4中,提供了完整的回溯。
答案 2 :(得分:2)
我做了一个装饰器实现,如下所示。
请注意functools.wraps
的使用情况,否则multiprocessing
会失败。
def full_traceback(func):
import traceback, functools
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
msg = "{}\n\nOriginal {}".format(e, traceback.format_exc())
raise type(e)(msg)
return wrapper
可以在https://stackoverflow.com/a/43223455中找到一个示例。
正如 Paige Lo 所提到的,现在get
的{{1}}方法在Python 3中返回完整的回溯,请参阅http://bugs.python.org/issue13831。