Chcę zapisać nazwę błędu i szczegóły śledzenia w zmiennej. Oto moja próba.
import sys
try:
try:
print x
except Exception, ex:
raise NameError
except Exception, er:
print "0", sys.exc_info()[0]
print "1", sys.exc_info()[1]
print "2", sys.exc_info()[2]
Wynik:
0 <type 'exceptions.NameError'>
1
2 <traceback object at 0xbd5fc8>
Pożądane wyjście:
0 NameError
1
2 Traceback (most recent call last):
File "exception.py", line 6, in <module>
raise NameError
PS Wiem, że można to łatwo zrobić za pomocą modułu traceback, ale chcę poznać tutaj użycie obiektu sys.exc_info () [2].
python
exception-handling
codersofthedark
źródło
źródło
<python install path>/Lib/traceback.py
), aby uzyskać więcej informacji.Odpowiedzi:
Oto jak to robię:
Powinieneś jednak przyjrzeć się dokumentacji śledzenia , ponieważ możesz znaleźć bardziej odpowiednie metody, w zależności od tego, jak chcesz później przetwarzać zmienną ...
źródło
sys.exc_info()[2].tb_frame.f_code.co_names[3]
ale to w ogóle nie ma sensu ... Jeślitraceback
w standardowej bibliotece jest jakiś moduł , to jest ku temu powód ... :)traceback.format_exception(*sys.exc_info())
jest sposobem na to. Ale to funkcjonalnie odpowiadatraceback.format_exc()
.sys.exc_info () zwraca krotkę z trzema wartościami (typ, wartość, śledzenie).
Na przykład w następującym programie
Teraz, jeśli wydrukujemy krotkę, wartości będą takie.
Powyższe szczegóły można również pobrać, po prostu drukując wyjątek w formacie łańcucha.
źródło
Użyj,
traceback.extract_stack()
jeśli chcesz mieć wygodny dostęp do nazw modułów i funkcji oraz numerów linii.Użyj,
''.join(traceback.format_stack())
jeśli potrzebujesz tylko ciągu, który wygląda jak danetraceback.print_stack()
wyjściowe.Zauważ, że nawet z
''.join()
tobą otrzymasz ciąg wieloliniowy, ponieważ elementyformat_stack()
zawierają\n
. Zobacz dane wyjściowe poniżej.Pamiętaj o tym
import traceback
.Oto wynik z
traceback.extract_stack()
. Dodano formatowanie w celu zwiększenia czytelności.Oto wynik z
''.join(traceback.format_stack())
. Dodano formatowanie w celu zwiększenia czytelności.źródło
Zachowaj ostrożność podczas wyjmowania obiektu wyjątku lub obiektu śledzenia z procedury obsługi wyjątków, ponieważ powoduje to cykliczne odwołania i
gc.collect()
nie powiedzie się ich zebranie. Wydaje się, że jest to szczególny problem w środowisku notebooków ipython / jupyter, w którym obiekt śledzenia nie jest czyszczony we właściwym czasie, a nawet jawne wywołaniegc.collect()
wfinally
sekcji nic nie daje. I to jest ogromny problem, jeśli masz jakieś ogromne obiekty, które nie odzyskują pamięci z tego powodu (np. CUDA z wyjątków pamięci, które bez tego rozwiązania wymagają pełnego restartu jądra, aby odzyskać).Ogólnie rzecz biorąc, jeśli chcesz zapisać obiekt śledzenia, musisz wyczyścić go z odniesień do
locals()
, na przykład:W przypadku notatnika jupyter musisz to zrobić przynajmniej wewnątrz obsługi wyjątków:
Przetestowano w Pythonie 3.7.
ps problem z ipython lub jupyter notebook env polega na tym, że ma
%tb
magię, która zapisuje dane śledzenia i udostępnia je w dowolnym momencie później. W rezultacie żadnalocals()
we wszystkich ramkach uczestniczących w śledzeniu nie zostanie zwolniona, dopóki notebook nie wyjdzie lub inny wyjątek nadpisze poprzednio zapisany ślad. To jest bardzo problematyczne. Nie powinien przechowywać danych śledzenia bez czyszczenia ramek. Poprawka przesłana tutaj .źródło
Obiekt może służyć jako parametr w
Exception.with_traceback()
funkcji:źródło