Ich schreibe ein Programm, das 10 Websites analysiert, Datendateien findet, die Dateien speichert und sie dann analysiert, um Daten zu erstellen, die problemlos in der NumPy-Bibliothek verwendet werden können. Es gibt Unmengen von Fehlern, auf die diese Datei durch fehlerhafte Links, schlecht geformtes XML, fehlende Einträge und andere Dinge stößt, die ich noch nicht kategorisiert habe. Ich habe dieses Programm ursprünglich erstellt, um Fehler wie folgt zu behandeln:
try:
do_stuff()
except:
pass
Aber jetzt möchte ich Fehler protokollieren:
try:
do_stuff()
except Exception, err:
print Exception, err
Beachten Sie, dass dies zur späteren Überprüfung in eine Protokolldatei gedruckt wird. Dies druckt normalerweise sehr nutzlose Daten. Ich möchte genau die gleichen Zeilen drucken, die gedruckt werden, wenn der Fehler ausgelöst wird, ohne dass try die Ausnahme abfängt. Ich möchte jedoch nicht, dass mein Programm angehalten wird, da es in einer Reihe von for-Schleifen verschachtelt ist, die ich möchte bis zur Fertigstellung sehen.
quelle
print(sys.exc_info()[0]
druckt<class 'Exception'>
.Wenn Sie debuggen und nur den aktuellen Stack-Trace anzeigen möchten, können Sie einfach Folgendes aufrufen:
traceback.print_stack()
Es ist nicht erforderlich, eine Ausnahme manuell auszulösen, um sie erneut abzufangen.
quelle
Wenn Sie Ihr Programm bei einem Fehler nicht anhalten möchten, müssen Sie diesen Fehler mit einem Versuch / außer behandeln:
Um den vollständigen Traceback zu extrahieren, verwenden wir das
traceback
Modul aus der Standardbibliothek:Und um einen anständig komplizierten Stacktrace zu erstellen, um zu demonstrieren, dass wir den vollständigen Stacktrace erhalten:
Drucken
Verwenden Sie die Methode, um den vollständigen Traceback zu drucken
traceback.print_exc
:Welche Drucke:
Besser als drucken, protokollieren:
Es wird jedoch empfohlen, einen Logger für Ihr Modul einzurichten. Es kennt den Namen des Moduls und kann Ebenen ändern (unter anderem Attribute wie Handler).
In diesem Fall möchten Sie
logger.exception
stattdessen die Funktion:Welche Protokolle:
Oder vielleicht möchten Sie nur die Zeichenfolge. In diesem Fall möchten Sie
traceback.format_exc
stattdessen die Funktion:Welche Protokolle:
Fazit
Und für alle drei Optionen erhalten wir dieselbe Ausgabe wie bei einem Fehler:
quelle
traceback.print_exc()
gibt nur den letzten Aufruf zurück: Wie gelingt es Ihnen, mehrere Ebenen des Stapels (und möglicherweise alle Ebenen?) zurückzugebenraise
Verkettung oder Ausnahmeverkettung durch oder verstecken Sie den ursprünglichen Traceback? siehe stackoverflow.com/questions/2052390/…Verwenden Sie
print
s nicht zum Protokollieren, es gibt ein stabiles, bewährtes und gut durchdachtes stdlib-Modul, um dies zu tun :logging
. Sie sollten es auf jeden Fall stattdessen verwenden.Zweitens wird nicht versucht eine tun Chaos mit nicht verwandten Tool , wenn es stammt und einfacher Ansatz. Hier ist es:
Das ist es. Du bist jetzt fertig.
Erklärung für alle, die daran interessiert sind, wie die Dinge unter der Haube funktionieren
Was
log.exception
tatsächlich getan wird, ist nur ein Aufruf vonlog.error
(dh ein Ereignis mit Ebene protokollierenERROR
) und dann ein Traceback drucken.Warum ist es besser?
Nun, hier sind einige Überlegungen:
Warum sollte niemand
traceback
Logger benutzen oder anrufenexc_info=True
oder sich die Hände schmutzig machensys.exc_info
?Nur weil! Sie existieren alle für unterschiedliche Zwecke. Beispielsweise unterscheidet sich
traceback.print_exc
die Ausgabe ein wenig von den vom Interpreter selbst erzeugten Tracebacks. Wenn Sie es verwenden, werden Sie jeden verwirren, der Ihre Protokolle liest, sie werden ihre Köpfe gegen sie schlagen.Das Übergeben
exc_info=True
, um Anrufe zu protokollieren, ist einfach unangemessen. Es ist jedoch nützlich, wenn Sie behebbare Fehler abfangen und diese (z. B. mitINFO
Level) auch mit Tracebacks protokollieren möchten , dalog.exception
nur Protokolle mit nur einem Level erstellt werden.ERROR
.Und Sie sollten auf jeden Fall vermeiden, mit
sys.exc_info
so viel wie möglich herumzuspielen . Es ist einfach keine öffentliche Schnittstelle, es ist eine interne - Sie können sie verwenden, wenn Sie definitiv wissen, was Sie tun. Es ist nicht nur zum Drucken von Ausnahmen gedacht.quelle
logging.exception()
. Sie müssen keine Protokollinstanz erstellen, es sei denn, Sie haben spezielle Anforderungen.Zusätzlich zur Antwort von @Aaron Hall können Sie, wenn Sie sich anmelden, aber nicht verwenden möchten
logging.exception()
(da es sich auf der FEHLER-Ebene anmeldet), eine niedrigere Ebene verwenden und bestehenexc_info=True
. z.Bquelle
Um die genaue Stapelverfolgung als Zeichenfolge zu erhalten, die ausgelöst worden wäre, wenn kein Versuch / Ausnahme vorhanden wäre, um darüber zu treten, platzieren Sie diese einfach in dem Block "Ausgenommen", der die betreffende Ausnahme abfängt.
So verwenden Sie es (vorausgesetzt, es
flaky_func
ist definiert undlog
ruft Ihr bevorzugtes Protokollierungssystem auf):Es ist eine gute Idee,
KeyboardInterrupt
s zu fangen und erneut zu erhöhen , damit Sie das Programm weiterhin mit Strg-C beenden können. Die Protokollierung liegt außerhalb des Bereichs der Frage, aber eine gute Option ist die Protokollierung . Dokumentation für die Sys- und Traceback- Module.quelle
desired_trace = traceback.format_exc()
. Alssys.exc_info()
Argument zu übergeben war nie das Richtige, wird aber in Python 2 stillschweigend ignoriert - aber nicht in Python 3 (3.6.4 sowieso).KeyboardInterrupt
wird nicht (direkt oder indirekt) von abgeleitetException
. (Beide sind abgeleitet vonBaseException
.) Dies bedeutet,except Exception:
dass niemals ein gefangen wirdKeyboardInterrupt
, und daherexcept KeyboardInterrupt: raise
ist das völlig unnötig.traceback.format_exc(sys.exc_info())
funktioniert nicht für mich mit Python 3.6.10Sie müssen den try / außer in den innersten Loop legen, in dem der Fehler auftreten kann, d. H.
... und so weiter
Mit anderen Worten, Sie müssen Anweisungen, die beim Versuch fehlschlagen können, außer so spezifisch wie möglich, in die innerste Schleife wie möglich einschließen.
quelle
Eine Bemerkung zu den Kommentaren dieser Antwort :
print(traceback.format_exc())
macht einen besseren Job für mich alstraceback.print_exc()
. Bei letzterem wird dashello
manchmal seltsamerweise mit dem Traceback-Text "gemischt", beispielsweise wenn beide gleichzeitig in stdout oder stderr schreiben möchten, was zu einer seltsamen Ausgabe führt (zumindest beim Erstellen aus einem Texteditor heraus und beim Anzeigen der Ausgabe im Bereich "Ergebnisse erstellen").Also benutze ich:
quelle
Ich sehe dies in keiner der anderen Antworten erwähnt. Wenn Sie ein Ausnahmeobjekt aus irgendeinem Grund weitergeben ...
In Python 3.5+ können Sie mit traceback.TracebackException.from_exception () einen Trace von einem Exception-Objekt abrufen . Zum Beispiel:
Der obige Code führt jedoch zu:
Dies sind nur zwei Ebenen des Stapels, im Gegensatz zu dem, was auf dem Bildschirm gedruckt worden wäre, wenn die Ausnahme ausgelöst
stack_lvl_2()
und nicht abgefangen worden wäre (kommentieren Sie das aus# raise
Zeile aus).Soweit ich weiß, liegt dies daran, dass eine Ausnahme
stack_lvl_3()
in diesem Fall nur die aktuelle Ebene des Stapels aufzeichnet, wenn dieser ausgelöst wird. Wenn es wieder durch den Stapel geleitet wird, werden weitere Ebenen hinzugefügt__traceback__
. Aber wir haben es abgefangenstack_lvl_2()
, was bedeutet, dass es nur Level 3 und 2 aufnehmen musste. Um die vollständige Spur zu erhalten, wie sie auf stdout gedruckt ist, müssten wir sie auf der höchsten (niedrigsten?) Ebene fangen:Was in ... resultiert:
Beachten Sie, dass der Stapeldruck unterschiedlich ist und die erste und die letzte Zeile fehlen. Weil es anders ist
format()
.Wenn Sie die Ausnahme so weit wie möglich von dem Punkt entfernt abfangen, an dem sie ausgelöst wurde, wird der Code einfacher und es werden mehr Informationen bereitgestellt.
quelle
Ruft den vollständigen Traceback als String vom Ausnahmeobjekt mit ab
traceback.format_exception
Wenn Sie nur das Ausnahmeobjekt haben, können Sie den Traceback als Zeichenfolge von jedem Punkt des Codes in Python 3 abrufen mit:
Vollständiges Beispiel:
Ausgabe:
Dokumentation: https://docs.python.org/3.7/library/traceback.html#traceback.format_exception
Siehe auch: Traceback-Informationen aus einem Ausnahmeobjekt extrahieren
Getestet in Python 3.7.3.
quelle
Sie möchten das Traceback- Modul. Damit können Sie Stack-Dumps drucken, wie es Python normalerweise tut. Insbesondere druckt die Funktion print_last die letzte Ausnahme und eine Stapelverfolgung.
quelle
Wenn Sie bereits ein Fehlerobjekt haben und das Ganze drucken möchten, müssen Sie diesen etwas umständlichen Aufruf ausführen:
Das stimmt,
print_exception
dauert drei Positionsargumente: Die Art der Ausnahme, das tatsächlichen Ausnahmeobjekts, und die eigenen internen Zurückverfolgungs Unterkunft Ausnahme.In Python 3.5 oder höher ist das
type(err)
optional ... aber es ist ein Positionsargument, sodass Sie an seiner Stelle immer noch None explizit übergeben müssen.Ich habe keine Ahnung, warum das alles nicht gerecht ist
traceback.print_exception(err)
. Warum Sie jemals einen Fehler zusammen mit einem anderen Traceback als dem, der zu diesem Fehler gehört, ausdrucken möchten, ist mir ein Rätsel.quelle