Ответ на этот вопрос зависит от версии Python, которую вы используете.
В Python 3
Все просто: исключения имеют __traceback__
атрибут, содержащий трассировку. Этот атрибут также доступен для записи и может быть удобно установлен с помощью with_traceback
метода исключений:
raise Exception("foo occurred").with_traceback(tracebackobj)
Эти функции минимально описаны в raise
документации.
Вся заслуга в этой части ответа принадлежит Виктору, который первым опубликовал эту информацию . Я включаю его сюда только потому, что этот ответ застрял наверху, а Python 3 становится все более распространенным.
В Python 2
Это досадно сложно. Проблема с трассировкой заключается в том, что у них есть ссылки на кадры стека, а кадры стека имеют ссылки на трассировки, которые имеют ссылки на кадры стека, которые имеют ссылки на ... вы поняли. Это вызывает проблемы для сборщика мусора. (Спасибо ecatmur за первое указание на это.)
Хороший способ решить эту проблему - хирургическим путем разорвать цикл после выхода из except
предложения, что и делает Python 3. Решение Python 2 намного уродливее: вам предоставляется специальная функция sys.exc_info()
, которая работает только внутри except
предложения . Он возвращает кортеж, содержащий исключение, тип исключения и трассировку для любого исключения, которое в настоящее время обрабатывается.
Итак, если вы находитесь внутри except
предложения, вы можете использовать вывод sys.exc_info()
вместе с traceback
модулем для выполнения различных полезных вещей:
>>> import sys, traceback
>>> def raise_exception():
... try:
... raise Exception
... except Exception:
... ex_type, ex, tb = sys.exc_info()
... traceback.print_tb(tb)
... finally:
... del tb
...
>>> raise_exception()
File "<stdin>", line 3, in raise_exception
Но, как указывает ваше редактирование, вы пытаетесь получить трассировку, которая была бы напечатана, если бы ваше исключение не было обработано, после того, как оно уже было обработано. Это гораздо более сложный вопрос. К сожалению, sys.exc_info
возвращается, (None, None, None)
если исключение не обрабатывается. Другие связанные sys
атрибуты тоже не помогают. sys.exc_traceback
устарел и не определен, если исключение не обрабатывается; sys.last_traceback
кажется идеальным, но, похоже, он определяется только во время интерактивных сеансов.
Если вы можете контролировать, как возникает исключение, вы можете использовать inspect
и настраиваемое исключение для хранения некоторой информации. Но я не совсем уверен, как это сработает.
По правде говоря, перехват и возврат исключения - дело необычное. Это может быть признаком того, что вам все равно нужно провести рефакторинг.