17

我想知道当通过多处理模块执行的函数内部存在异常时获取堆栈跟踪的最佳方法。这是一个例子:

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

有没有办法在没有所有样板代码的情况下获得这种行为?如果没有,不包括此功能的原因是什么?

编辑:可以为样板代码使用装饰器,但我不知道标准库中是否包含这样的装饰器?

4

3 回答 3

11

看起来你应该避免从你的 main 函数中引发异常。相反,您可以捕获它,将其视为返回给主程序的值,然后在那里引发它。 在 Python 中重新抛出异常有更多细节。

于 2009-12-10T15:21:13.830 回答
4

在 Python 3.4 中,提供了完整的回溯。

http://bugs.python.org/issue13831

于 2014-07-14T16:16:07.007 回答
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中找到一个示例。

蟒蛇 3

正如Paige Lo所提到的,现在在 Python 3get中返回完整回溯的方法,请参见http://bugs.python.org/issue13831multiprocessing.pool.Async

于 2017-04-05T06:44:17.107 回答