W jaki sposób sprawisz, że nieprzechwycone wyjątki będą wysyłane przez logging
moduł, a nie do stderr
?
Zdaję sobie sprawę, że najlepszym sposobem na to byłoby:
try:
raise Exception, 'Throwing a boring exception'
except Exception, e:
logging.exception(e)
Ale moja sytuacja jest taka, że byłoby naprawdę fajnie, gdyby logging.exception(...)
były wywoływane automatycznie, gdy wyjątek nie zostanie złapany.
python
logging
exception-handling
Jacob Marble
źródło
źródło
Odpowiedzi:
Jak zauważył Ned,
sys.excepthook
jest wywoływana za każdym razem, gdy wyjątek jest podnoszony i nieprzechwycony. Praktyczna konsekwencja tego jest taka, że w swoim kodzie możesz nadpisać domyślne zachowanie,sys.excepthook
aby robić, co chcesz (w tym używaćlogging.exception
).Jako przykład słomianego człowieka:
Zastąp
sys.excepthook
:Popełnij oczywisty błąd składni (pomiń dwukropek) i odzyskaj niestandardowe informacje o błędzie:
Aby uzyskać więcej informacji
sys.excepthook
, przeczytaj dokumentację .źródło
type
jako argumentu funkcji, chociaż IDE będą narzekać na ukrywanie globalnegotype
(podobnie jakvar self = this
w Javascript). To naprawdę nie ma znaczenia, chyba że potrzebujesz dostępu dotype
obiektu wewnątrz swojej funkcji, w takim przypadku możesz użyćtype_
zamiast tego jako argumentu.sys.excepthook
nie jest wywoływana, gdy wyjątek jest „podniesione”. Jest wywoływana, gdy program ma zamiar zakończyć działanie z powodu nieprzechwyconego wyjątku, który nie może się zdarzyć więcej niż raz.Oto kompletny mały przykład, który zawiera również kilka innych sztuczek:
Zignoruj KeyboardInterrupt, aby program konsoli mógł wyjść za pomocą Ctrl + C.
W celu sformatowania wyjątku polegaj całkowicie na module rejestrowania języka Python.
Użyj niestandardowego programu rejestrującego z przykładową obsługą. To zmienia nieobsługiwany wyjątek, aby przejść do standardowego wyjścia zamiast na stderr, ale można dodać wszystkie rodzaje programów obsługi w tym samym stylu do obiektu rejestratora.
źródło
logger.critical()
wewnątrz przewodnika excepthook, ponieważ nieprzechwycony Wyjątkiem jest dość krytyczny powiedziałbym.logging.basicConfig(level=logging.DEBUG, filename="debug.log", format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ale nie pomogło.Metoda
sys.excepthook
zostanie wywołana, jeśli wyjątek nie zostanie przechwycony: http://docs.python.org/library/sys.html#sys.excepthookźródło
type
instancję?sys.excepthook
?Dlaczego nie:
Oto wynik z
sys.excepthook
jak widać powyżej:Oto wynik z
sys.excepthook
wykomentowanym:Jedyna różnica polega na tym, że ten pierwszy ma
ERROR:root:Unhandled exception:
na początku pierwszej linii.źródło
sys.stderr
.Aby zbudować na odpowiedzi Jacindy, ale używając obiektu rejestrującego:
źródło
functools.partial()
zamiast lambda. Zobacz: docs.python.org/2/library/functools.html#functools.partialZawiń wywołanie wpisu aplikacji w
try...except
blok, abyś mógł przechwycić i zarejestrować (i być może ponownie zgłosić) wszystkie nieprzechwycone wyjątki. Np. Zamiast:Zrób to:
źródło
Może mógłbyś zrobić coś na górze modułu, który przekierowuje stderr do pliku, a następnie zarejestrować ten plik na dole
źródło
Chociaż odpowiedź @ gnu_lorien dała mi dobry punkt wyjścia, mój program zawiesza się przy pierwszym wyjątku.
Przyszedłem z niestandardowym (i / lub) ulepszonym rozwiązaniem, które po cichu rejestruje Wyjątki funkcji, które są ozdobione
@handle_error
.źródło
Aby odpowiedzieć na pytanie pana Zeusa omówione w sekcji komentarzy zaakceptowanej odpowiedzi, używam tego do logowania niezłapanych wyjątków w interaktywnej konsoli (testowane z PyCharm 2018-2019). Dowiedziałem się,
sys.excepthook
że nie działa w powłoce Pythona, więc zajrzałem głębiej i stwierdziłem, że mogęsys.exc_info
zamiast tego użyć . Jednaksys.exc_info
nie przyjmuje żadnych argumentów, inaczejsys.excepthook
niż przyjmuje 3 argumenty.Tutaj używam obu
sys.excepthook
isys.exc_info
do rejestrowania obu wyjątków w interaktywnej konsoli i skrypcie z funkcją opakowania. Aby dołączyć funkcję hook do obu funkcji, mam dwa różne interfejsy w zależności od tego, czy podano argumenty, czy nie.Oto kod:
Konfigurację logowania można znaleźć w odpowiedzi gnu_lorien.
źródło
W moim przypadku (przy użyciu
python 3
) podczas korzystania z odpowiedzi @Jacindy zawartość śledzenia nie została wydrukowana. Zamiast tego, po prostu drukuje sam obiekt:<traceback object at 0x7f90299b7b90>
.Zamiast tego robię:
źródło