Подтвердить что ты не робот

Каков наилучший способ получить stacktrace при использовании многопроцессорности?

Мне интересно, как получить стек, когда есть исключение внутри функции, выполняемой через модуль многопроцессорности. Вот пример:

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.

Таким образом, нет полезной stacktrace, что довольно раздражает. Мое текущее решение для этого:

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

Есть ли способ получить это поведение без кода шаблона? Если нет, в чем причина не включать эту функцию?

Изменить: можно использовать декоратор для шаблона кода, но я не знаю, включен ли такой декоратор в стандартную библиотеку?

4b9b3361

Ответ 1

Похоже, вам следует избегать привлечения исключения из вашей основной функции. Вместо этого вы можете поймать его, рассматривать его как значение, возвращаемое основной программе, а затем поднять его там. Повторные выбросы исключений в Python содержат более подробную информацию.

Ответ 3

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

Пример можно найти в fooobar.com/info/107955/....

Python 3

Как полагается Paige Lo, теперь метод get multiprocessing.pool.Async возвращает полную трассировку в Python 3, см. http://bugs.python.org/issue13831.