Jak mogę rejestrować błędy Pythona?
try:
do_something()
except:
# How can I log my exception here, complete with its traceback?
Jak mogę rejestrować błędy Pythona?
try:
do_something()
except:
# How can I log my exception here, complete with its traceback?
Użyj logging.exception
z modułu except:
obsługi / bloku, aby zarejestrować bieżący wyjątek wraz z informacjami o śledzeniu, poprzedzonymi komunikatem.
import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG)
logging.debug('This message should go to the log file')
try:
run_my_stuff()
except:
logging.exception('Got exception on main handler')
raise
Teraz patrząc na plik dziennika /tmp/logging_example.out
:
DEBUG:root:This message should go to the log file
ERROR:root:Got exception on main handler
Traceback (most recent call last):
File "/tmp/teste.py", line 9, in <module>
run_my_stuff()
NameError: name 'run_my_stuff' is not defined
logger = logging.getLogger('yourlogger')
, musisz napisać,logger.exception('...')
aby ten działał ...Użyj
exc_info
opcji może być lepsze, pozostaje ostrzeżenie lub tytuł błędu:źródło
exc_info=
nazywa się kwarg; dzięki!logging.exception
Moja praca ostatnio zleciła mi rejestrowanie wszystkich danych śledzenia / wyjątków z naszej aplikacji. Wypróbowałem wiele technik, które inni opublikowali w Internecie, takich jak ta powyżej, ale zdecydowałem się na inne podejście. Zastępowanie
traceback.print_exception
.Mam napis na http://www.bbarrows.com/ Byłby o wiele łatwiejszy do odczytania, ale wkleię go również tutaj.
Kiedy otrzymałem zadanie rejestrowania wszystkich wyjątków, które nasze oprogramowanie może napotkać na wolności, wypróbowałem wiele różnych technik, aby zarejestrować nasze śledzenie wyjątków w Pythonie. Na początku pomyślałem, że hak wyjątków systemu Pythona, sys.excepthook, będzie idealnym miejscem do wstawienia kodu logowania. Próbowałem czegoś podobnego do:
To działało w przypadku głównego wątku, ale wkrótce odkryłem, że mój sys.excepthook nie będzie istniał w żadnym nowym wątku, który rozpoczął mój proces. To ogromny problem, ponieważ w tym projekcie prawie wszystko dzieje się w wątkach.
Po przeszukaniu go i przeczytaniu dużej ilości dokumentacji, najbardziej pomocne informacje, które znalazłem, pochodziły z narzędzia do śledzenia problemów w Pythonie.
Pierwszy post w wątku pokazuje działający przykład
sys.excepthook
NIE utrzymującego się w wątkach (jak pokazano poniżej). Najwyraźniej jest to oczekiwane zachowanie.Komunikaty w tym wątku dotyczącym Pythona naprawdę skutkują 2 sugerowanymi hackami. Albo podklasę
Thread
i zawiń metodę run w naszej własnej try z wyjątkiem bloku, aby przechwytywać i rejestrować wyjątki, lub małpę łatkęthreading.Thread.run
do uruchomienia we własnym try, z wyjątkiem blokowania i rejestrowania wyjątków.Pierwsza metoda tworzenia podklas
Thread
wydaje mi się mniej elegancka w twoim kodzie, ponieważ musiałbyś importować i używać swojej niestandardowejThread
klasy WSZĘDZIE, gdzie chciałbyś mieć wątek logowania. Skończyło się to kłopotem, ponieważ musiałem przeszukać całą naszą bazę kodu i zastąpić wszystko normalneThreads
tym niestandardowymThread
. Jednak było jasne, co toThread
robi, i byłoby łatwiej dla kogoś zdiagnozować i debugować, gdyby coś poszło nie tak z niestandardowym kodem logowania. Niestandardowy wątek rejestrowania może wyglądać następująco:Druga metoda patchowania małp
threading.Thread.run
jest fajna, ponieważ mogłem ją po prostu uruchomić raz zaraz po__main__
i instrumentować mój kod logowania we wszystkich wyjątkach. Poprawianie małp może być denerwujące przy debugowaniu, ponieważ zmienia oczekiwaną funkcjonalność czegoś. Sugerowana łatka z narzędzia do śledzenia problemów Pythona to:Dopiero gdy zacząłem testować rejestrowanie wyjątków, zdałem sobie sprawę, że wszystko idzie źle.
Aby przetestować, umieściłem plik
gdzieś w moim kodzie. Jednak zawijanie metody, która wywołała tę metodę, było blokiem try z wyjątkiem, który wypisał traceback i połknął wyjątek. To było bardzo frustrujące, ponieważ widziałem, że traceback przenosi wydruk do STDOUT, ale nie został zarejestrowany. Wtedy zdecydowałem, że o wiele łatwiejszą metodą rejestrowania śladów jest po prostu małpa łata metodę, której cały kod Pythona używa do drukowania samych śladów, traceback.print_exception. Skończyło się na czymś podobnym do następującego:
Ten kod zapisuje dane śledzenia w buforze ciągów i rejestruje je w dzienniku ERROR. Mam niestandardowy program obsługi rejestrowania, który konfiguruje rejestrator „customLogger”, który pobiera dzienniki poziomu BŁĘDU i wysyła je do domu do analizy.
źródło
add_custom_print_exception
wygląda na to, że nie ma go w witrynie, do której prowadzą linki, a zamiast tego jest tam całkiem inny końcowy kod. Który z nich jest lepszy / bardziej ostateczny i dlaczego? Dzięki!logger.error(traceback.format_tb())
(lub format_exc (), jeśli chcesz również informacje o wyjątku).Możesz rejestrować wszystkie nieprzechwycone wyjątki w głównym wątku, przypisując procedurę obsługi do
sys.excepthook
, być może używającexc_info
parametru funkcji logowania Pythona :Jeśli jednak Twój program używa wątków, pamiętaj, że wątki utworzone za pomocą nie
threading.Thread
będą wyzwalane, gdy wystąpi w nich nieprzechwycony wyjątek, jak wspomniano w numerze 1230540 dotyczącym śledzenia problemów w języku Python. Sugerowano tam kilka hacków, aby obejść to ograniczenie, np. Małpa łatanie w celu nadpisania alternatywną metodą, która zawija oryginał w bloku i wywołuje z wnętrza bloku. Alternatywnie możesz po prostu ręcznie zawinąć punkt wejścia dla każdego z wątków w / w sobie.sys.excepthook
Thread.__init__
self.run
run
try
sys.excepthook
except
try
except
źródło
Nieprzechwycone komunikaty o wyjątkach trafiają do STDERR, więc zamiast implementować logowanie w samym Pythonie, możesz wysłać STDERR do pliku przy użyciu dowolnej powłoki, której używasz do uruchomienia skryptu Pythona. W skrypcie Bash możesz to zrobić za pomocą przekierowania wyjścia, jak opisano w przewodniku BASH .
Przykłady
Dołącz błędy do pliku, inne dane wyjściowe do terminala:
Nadpisz plik z przeplatanym wyjściem STDOUT i STDERR:
źródło
Czego szukałem:
Widzieć:
źródło
Możesz uzyskać śledzenie za pomocą loggera na dowolnym poziomie (DEBUG, INFO, ...). Zwróć uwagę, że użycie
logging.exception
poziomu to ERROR.EDYTOWAĆ:
To też działa (używając Pythona 3.6)
źródło
Oto wersja korzystająca z sys.excepthook
źródło
{traceback.format_exc()}
zamiast{traceback.format_tb(stack)}
?może nie tak stylowy, ale łatwiejszy:
źródło
Oto prosty przykład zaczerpnięty z dokumentacji Pythona 2.6 :
źródło