在使用多进程时获取栈追踪的最佳方法是什么?

17 投票
3 回答
2953 浏览
提问于 2025-04-15 16:52

我在想,如何在使用多进程模块执行的函数里出现异常时,获取最好的堆栈跟踪信息。下面是一个例子:

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.Asyncget 方法会返回完整的错误追踪信息,具体可以查看这个链接:http://bugs.python.org/issue13831

4

在Python 3.4版本中,会提供完整的错误追踪信息。

http://bugs.python.org/issue13831

11

看起来你应该避免在主函数中直接抛出异常。相反,你可以先捕获这个异常,把它当作一个返回值,然后再在主程序中抛出它。想了解更多细节,可以查看这个链接:在Python中重新抛出异常

撰写回答