在使用多进程时获取栈追踪的最佳方法是什么?
我在想,如何在使用多进程模块执行的函数里出现异常时,获取最好的堆栈跟踪信息。下面是一个例子:
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
有没有办法在不写那么多重复代码的情况下实现这个功能?如果没有,为什么不把这个功能放进去呢?
补充:可以用装饰器来处理这些重复代码,但我不知道标准库里有没有这样的装饰器?
3 个回答
2
Python 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。
Python 3
正如 Paige Lo 提到的,现在在 Python 3 中,multiprocessing.pool.Async
的 get
方法会返回完整的错误追踪信息,具体可以查看这个链接:http://bugs.python.org/issue13831。
4
在Python 3.4版本中,会提供完整的错误追踪信息。
11
看起来你应该避免在主函数中直接抛出异常。相反,你可以先捕获这个异常,把它当作一个返回值,然后再在主程序中抛出它。想了解更多细节,可以查看这个链接:在Python中重新抛出异常。