Wie kann ich meine Python-Fehler protokollieren?
try:
do_something()
except:
# How can I log my exception here, complete with its traceback?
Wie kann ich meine Python-Fehler protokollieren?
try:
do_something()
except:
# How can I log my exception here, complete with its traceback?
Verwenden Sie diese Option logging.exception
aus dem except:
Handler / Block heraus, um die aktuelle Ausnahme zusammen mit den Ablaufverfolgungsinformationen zu protokollieren, denen eine Nachricht vorangestellt ist.
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
Schauen Sie sich nun die Protokolldatei an /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')
Sie schreibenlogger.exception('...')
müssen, damit dies funktioniert ...Verwendungsoptionen
exc_info
können besser sein, bleibt Warnung oder Fehlertitel:quelle
exc_info=
Kwarg heißt; Vielen Dank!logging.exception
Mein Job hat mich kürzlich beauftragt, alle Tracebacks / Ausnahmen aus unserer Anwendung zu protokollieren. Ich habe zahlreiche Techniken ausprobiert, die andere online gestellt hatten, wie die oben beschriebene, mich aber für einen anderen Ansatz entschieden. Überschreiben
traceback.print_exception
.Ich habe einen Artikel unter http://www.bbarrows.com/. Das wäre viel einfacher zu lesen, aber ich füge ihn auch hier ein.
Als ich mit der Protokollierung aller Ausnahmen beauftragt wurde, auf die unsere Software in der Natur stoßen könnte, habe ich verschiedene Techniken ausprobiert, um unsere Python-Ausnahme-Tracebacks zu protokollieren. Zuerst dachte ich, dass der Python-System-Ausnahme-Hook sys.excepthook der perfekte Ort wäre, um den Protokollierungscode einzufügen. Ich habe etwas Ähnliches versucht wie:
Dies funktionierte für den Hauptthread, aber ich stellte bald fest, dass mein sys.excepthook in keinem neuen Thread vorhanden sein würde, den mein Prozess gestartet hatte. Dies ist ein großes Problem, da in diesem Projekt fast alles in Threads geschieht.
Nachdem ich gegoogelt und viele Dokumentationen gelesen hatte, fand ich die hilfreichsten Informationen im Python Issue Tracker.
Der erste Beitrag im Thread zeigt ein Arbeitsbeispiel für das
sys.excepthook
NICHT-Fortbestehen über Threads (wie unten gezeigt). Anscheinend ist dies erwartetes Verhalten.Die Nachrichten in diesem Python Issue-Thread führen tatsächlich zu 2 vorgeschlagenen Hacks. Entweder Unterklasse
Thread
und Wrap der Run-Methode in unserem eigenen Versuch außer Block, um Ausnahmen oder Affen-Patch abzufangen und zu protokollierenthreading.Thread.run
, um in Ihrem eigenen Versuch außer Block auszuführen und die Ausnahmen zu protokollieren.Die erste Methode der Unterklasse
Thread
scheint mir in Ihrem Code weniger elegant zu sein, da Sie Ihre benutzerdefinierteThread
Klasse ÜBERALL importieren und verwenden müssten, wo immer Sie einen Protokollierungsthread haben möchten . Dies war ein Ärger, da ich unsere gesamte Codebasis durchsuchen und alles NormaleThreads
durch diesen Brauch ersetzen mussteThread
. Es war jedoch klar, was diesThread
tat, und es würde für jemanden einfacher sein, zu diagnostizieren und zu debuggen, wenn mit dem benutzerdefinierten Protokollierungscode ein Fehler auftrat. Ein benutzerdefinierter Protokollierungsthread könnte folgendermaßen aussehen:Die zweite Methode zum Patchen von Affen
threading.Thread.run
ist nett, da ich sie direkt danach einmal ausführen__main__
und meinen Protokollierungscode in allen Ausnahmen instrumentieren konnte. Das Patchen von Affen kann beim Debuggen jedoch ärgerlich sein, da es die erwartete Funktionalität von etwas ändert. Der vorgeschlagene Patch vom Python Issue Tracker war:Erst als ich anfing, meine Ausnahmeprotokollierung zu testen, wurde mir klar, dass ich alles falsch gemacht hatte.
Zum Testen hatte ich einen platziert
irgendwo in meinem Code. Das Umschließen einer Methode, die diese Methode aufrief, war jedoch ein Versuch mit Ausnahme eines Blocks, der den Traceback druckte und die Ausnahme verschluckte. Das war sehr frustrierend, weil ich sah, dass der Traceback auf STDOUT gedruckt, aber nicht protokolliert wurde. Dann entschied ich, dass eine viel einfachere Methode zum Protokollieren der Tracebacks darin bestand, die Methode zu patchen, mit der der gesamte Python-Code die Tracebacks selbst druckt, traceback.print_exception. Am Ende hatte ich etwas Ähnliches wie das Folgende:
Dieser Code schreibt den Traceback in einen String-Puffer und protokolliert ihn im Protokollierungsfehler. Ich habe einen benutzerdefinierten Protokollierungshandler eingerichtet, der den 'customLogger'-Logger eingerichtet hat, der die ERROR-Protokolle aufnimmt und zur Analyse nach Hause sendet.
quelle
add_custom_print_exception
scheint nicht auf der Site zu sein, auf die Sie verlinkt haben, und stattdessen gibt es dort einen ganz anderen endgültigen Code. Welches ist Ihrer Meinung nach besser / endgültiger und warum? Vielen Dank!logger.error(traceback.format_tb())
(oder format_exc () aufrufen, wenn Sie auch die Ausnahmeinformationen wünschen).Sie können alle nicht erfassten Ausnahmen im Hauptthread protokollieren, indem Sie einen Handler zuweisen
sys.excepthook
, möglicherweise mithilfe desexc_info
Parameters der Protokollierungsfunktionen von Python :Wenn Ihr Programm - Threads jedoch beachten , dann die Threads erstellt
threading.Thread
werden nicht Auslöser ,sys.excepthook
wenn eine abgefangene Ausnahme in ihnen auftritt, wie in angemerkt Ausgabe 1230540 auf Pythons issue tracker. Es wurden dort einige Hacks vorgeschlagen, um diese Einschränkung zu umgehen, z. B. das PatchenThread.__init__
von Affen zum Überschreibenself.run
mit einer alternativenrun
Methode, bei der das Original in einentry
Block eingeschlossen undsys.excepthook
aus demexcept
Block heraus aufgerufen wird. Alternativ können Sie nur manuell wickeln den Einstiegspunkt für jede Ihrer Fäden intry
/except
selbst.quelle
Nicht erfasste Ausnahmemeldungen werden an STDERR gesendet. Anstatt Ihre Protokollierung in Python selbst zu implementieren, können Sie STDERR mit einer beliebigen Shell, mit der Sie Ihr Python-Skript ausführen, an eine Datei senden. In einem Bash-Skript können Sie dies mit der Ausgabeumleitung tun, wie im BASH-Handbuch beschrieben .
Beispiele
Anhängen von Fehlern an Datei, andere Ausgabe an das Terminal:
Datei mit verschachtelter STDOUT- und STDERR-Ausgabe überschreiben:
quelle
Was ich gesucht habe:
Sehen:
quelle
Sie können den Traceback mit einem Logger auf jeder Ebene abrufen (DEBUG, INFO, ...). Beachten Sie, dass bei Verwendung
logging.exception
die Stufe FEHLER ist.BEARBEITEN:
Dies funktioniert auch (mit Python 3.6)
quelle
Hier ist eine Version, die sys.excepthook verwendet
quelle
{traceback.format_exc()}
statt{traceback.format_tb(stack)}
?vielleicht nicht so stylisch, aber einfacher:
quelle
Hier ist ein einfaches Beispiel aus der Python 2.6-Dokumentation :
quelle