Odpowiedź na to pytanie zależy od używanej wersji Pythona.
W Pythonie 3
To proste: wyjątki są wyposażone w __traceback__
atrybut zawierający dane śledzenia. Ten atrybut jest również zapisywalny i można go wygodnie ustawić za pomocą with_traceback
metody wyjątków:
raise Exception("foo occurred").with_traceback(tracebackobj)
Te funkcje są minimalnie opisane jako część raise
dokumentacji.
Cała zasługa tej części odpowiedzi należy się Vyctorowi, który jako pierwszy opublikował te informacje . Uwzględniam to tutaj tylko dlatego, że ta odpowiedź utknęła na górze, a Python 3 staje się coraz bardziej powszechny.
W Pythonie 2
To irytująco złożone. Problem z trackbackami polega na tym, że mają one odniesienia do ramek stosu, a ramki stosu mają odniesienia do elementów traceback, które mają odniesienia do ramek stosu, które mają odniesienia do ... rozumiesz. Powoduje to problemy dla odśmiecacza. (Dzięki ecatmur za pierwsze wskazanie).
Dobrym sposobem rozwiązania tego problemu byłoby chirurgiczne przerwanie cyklu po opuszczeniu except
klauzuli, co robi Python 3. Rozwiązanie w Pythonie 2 jest dużo brzydsze: masz do dyspozycji funkcję ad-hoc sys.exc_info()
, która działa tylko wewnątrz except
klauzuli . Zwraca krotkę zawierającą wyjątek, typ wyjątku i ślad zwrotny dla dowolnego wyjątku, który jest obecnie obsługiwany.
Więc jeśli jesteś wewnątrz except
klauzuli, możesz użyć danych wyjściowych sys.exc_info()
wraz z traceback
modułem do zrobienia różnych przydatnych rzeczy:
>>> 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
Ale jak wskazuje twoja edycja, próbujesz uzyskać dane śledzenia, które zostałyby wydrukowane, gdyby twój wyjątek nie został obsłużony, po tym, jak został już obsłużony. To znacznie trudniejsze pytanie. Niestety sys.exc_info
wraca, (None, None, None)
gdy żaden wyjątek nie jest obsługiwany. Inne powiązane sys
atrybuty też nie pomagają. sys.exc_traceback
jest przestarzały i niezdefiniowany, gdy żaden wyjątek nie jest obsługiwany; sys.last_traceback
wydaje się idealny, ale wydaje się, że jest definiowany tylko podczas sesji interaktywnych.
Jeśli możesz kontrolować sposób wywoływania wyjątku, możesz użyć inspect
i niestandardowego wyjątku do przechowywania niektórych informacji. Ale nie jestem do końca pewien, jak to zadziała.
Prawdę mówiąc, wyłapywanie i zwracanie wyjątku jest czymś niezwykłym. Może to oznaczać, że i tak musisz dokonać refaktoryzacji.