Каков наилучший способ получить 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
Есть ли способ получить это поведение без кода шаблона? Если нет, в чем причина не включать эту функцию?
Изменить: можно использовать декоратор для шаблона кода, но я не знаю, включен ли такой декоратор в стандартную библиотеку?
Ответы
Ответ 1
Похоже, вам следует избегать привлечения исключения из вашей основной функции. Вместо этого вы можете поймать его, рассматривать его как значение, возвращаемое основной программе, а затем поднять его там. Повторные выбросы исключений в Python содержат более подробную информацию.
Ответ 2
В Python 3.4 предусмотрена полная трассировка.
http://bugs.python.org/issue13831
Ответ 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.