Drukuję komunikaty o wyjątkach Pythona do pliku dziennika z logging.error
:
import logging
try:
1/0
except ZeroDivisionError as e:
logging.error(e) # ERROR:root:division by zero
Czy można wydrukować bardziej szczegółowe informacje na temat wyjątku i kodu, który go wygenerował, niż tylko ciąg wyjątku? Takie rzeczy jak numery linii lub ślady stosu byłyby świetne.
python
exception
logging
exception-handling
prawdopodobnie na plaży
źródło
źródło
exception
Metoda po prostu wywołujeerror(message, exc_info=1)
. Jak tylko przejdzieszexc_info
do dowolnej metody rejestrowania z kontekstu wyjątku, otrzymasz traceback.sys.excepthook
(patrz tutaj ), aby uniknąć konieczności owijania całego kodu w try / wyjątkiem.except Exception:
ponieważ nie używasze
w żaden sposób;)e
kiedy próbujesz interaktywnie debugować swój kod. :) Dlatego zawsze to uwzględniam.raise
na końcuexcept
zakresu. W przeciwnym razie działanie będzie kontynuowane, jakby wszystko było w porządku.Jedną fajną rzeczą w tym,
logging.exception
że odpowiedź SiggyF nie pokazuje, jest to, że możesz przekazać dowolną wiadomość, a rejestrowanie nadal pokaże pełne śledzenie ze wszystkimi szczegółami wyjątków:Przy domyślnym (w ostatnich wersjach) sposobie rejestrowania tylko błędów drukowania
sys.stderr
, wygląda to tak:źródło
''
jeśli naprawdę nie chcesz pisać wiadomości ... funkcja nie może zostać wywołana bez co najmniej jednego argumentu, więc musisz jej coś dać.Korzystanie z
exc_info
opcji może być lepsze, aby umożliwić wybór poziomu błędu (jeśli go użyjeszexception
, zawsze będzie on naerror
poziomie):źródło
logging.fatal
w bibliotece rejestrowania jest metoda? Tylko widzęcritical
.critical
, tak jakwarn
to jestwarning
.Cytowanie
Teraz
traceback
można go tutaj użyć.Użyj go w Pythonie 2 :
Użyj go w Pythonie 3 :
źródło
ex_traceback
pochodzi zex.__traceback__
Python 3, aleex_traceback
pochodzi zsys.exc_info()
Python 2.Jeśli używasz zwykłego dzienniki - wszystkie rekordy dziennika powinna odpowiadać tej reguły:
one record = one line
. Zgodnie z tą zasadą możesz używaćgrep
innych narzędzi do przetwarzania plików dziennika.Ale informacje śledzenia są wieloliniowe. Tak więc moją odpowiedzią jest rozszerzona wersja rozwiązania zaproponowanego przez zangw powyżej w tym wątku. Problem polega na tym, że linie śledzenia mogą mieć
\n
wewnątrz, więc musimy wykonać dodatkową pracę, aby pozbyć się zakończeń linii:Następnie (podczas analizy dzienników) możesz skopiować / wkleić wymagane wiersze śledzenia z pliku dziennika i wykonać następujące czynności:
Zysk!
źródło
Ta odpowiedź składa się z powyższych doskonałych.
W większości aplikacji nie będziesz dzwonić bezpośrednio do dziennika.exception (e). Najprawdopodobniej zdefiniowałeś niestandardowy rejestrator specyficzny dla aplikacji lub modułu w następujący sposób:
W takim przypadku wystarczy użyć programu rejestrującego, aby wywołać wyjątek (e) w następujący sposób:
źródło
Możesz zarejestrować ślad stosu bez wyjątku.
https://docs.python.org/3/library/logging.html#logging.Logger.debug
Przykład:
źródło
Trochę obróbki dekoratora (bardzo luźno zainspirowane Być może monadą i liftingiem). Możesz bezpiecznie usunąć adnotacje typu Python 3.6 i użyć starszego stylu formatowania wiadomości.
fallible.py
Próbny:
Możesz również zmodyfikować to rozwiązanie, aby zwracało coś nieco bardziej znaczącego niż
None
zexcept
części (lub nawet uczynić rozwiązanie ogólnym, podając tę wartość zwracaną wfallible
argumentach).źródło
W module logowania (jeśli jest to moduł niestandardowy) wystarczy włączyć informacje o stosie.
źródło
Jeśli możesz poradzić sobie z dodatkową zależnością, to użyj twisted.log, nie musisz jawnie rejestrować błędów, a także zwraca cały ślad i czas do pliku lub strumienia.
źródło
twisted
jest to dobra rekomendacja, ale ta odpowiedź tak naprawdę niewiele wnosi. Nie mówi, jak używaćtwisted.log
, ani jakie ma zalety w stosunku dologging
modułu ze standardowej biblioteki, ani nie wyjaśnia, co oznacza „nie musisz jawnie rejestrować błędów” .Czystym sposobem na to jest użycie,
format_exc()
a następnie parsowanie danych wyjściowych, aby uzyskać odpowiednią część:pozdrowienia
źródło
.split('\n')[-2]
co trzeba, to wyrzucić numer linii i ślad po wynikuformat_exc()
- przydatnych informacji, których normalnie potrzebujesz! Co więcej, nawet nie wykonuje dobrą robotę , że ; jeśli komunikat wyjątku zawiera nowy wiersz, to podejście spowoduje wydrukowanie tylko ostatniego wiersza komunikatu wyjątku - co oznacza, że utracisz klasę wyjątku i większość komunikatu wyjątku oprócz utraty śledzenia. -1.