python matplotlib - Trace-Back-Informationen aus einem Ausnahmeobjekt extrahieren




2 Answers

Die Antwort auf diese Frage hängt von der Version von Python ab, die Sie verwenden.

In Python 3

__traceback__ einfach: Ausnahmen sind mit einem __traceback__ Attribut ausgestattet, das das __traceback__ enthält. Dieses Attribut ist auch beschreibbar und kann bequem mit der Methode with_traceback von Ausnahmen festgelegt werden:

raise Exception("foo occurred").with_traceback(tracebackobj)

Diese Funktionen werden minimal als Teil der raise Dokumentation beschrieben.

Der ganze Kredit für diesen Teil der Antwort sollte an Vyctor gehen, der diese Information zuerst gepostet hat . Ich füge es hier nur ein, weil diese Antwort an der Spitze stecken bleibt und Python 3 immer häufiger wird.

In Python 2

Es ist ärgerlich komplex. Das Problem mit Tracebacks ist, dass sie Verweise auf Stack-Frames haben und Stack-Frames Verweise auf die Trace-Backs haben, die Verweise auf Stack-Frames haben , die Verweise auf ... haben. Sie erhalten die Idee. Dies verursacht Probleme für den Garbage Collector. (Danke an ecatmur für den ersten Hinweis darauf.)

Der beste Weg, dies zu lösen, wäre, den Zyklus nach dem Verlassen der except Klausel zu unterbrechen, was Python 3 tut. Die Python 2-Lösung ist viel hässlicher: Sie erhalten eine Ad-hoc-Funktion, sys.exc_info() , die nur innerhalb der sys.exc_info() Klausel funktioniert . Sie gibt ein Tupel zurück, das die Ausnahme, den Ausnahmetyp und das Traceback für die gerade behandelte Ausnahme enthält.

Wenn Sie also innerhalb der sys.exec_info() Klausel sind, können Sie die Ausgabe von sys.exec_info() zusammen mit dem traceback Modul verwenden, um verschiedene nützliche Dinge zu tun:

>>> import sys, traceback
>>> def raise_exception():
...     try:
...         raise Exception
...     except Exception:
...         ex_type, ex, tb = sys.exc_info()
...         traceback.print_tb(tb)
...     finally:
...         del tb
... 
>>> raise_exception()
  File "<stdin>", line 3, in raise_exception

Aber wie Ihre Editierung anzeigt, versuchen Sie, das Traceback zu erhalten, das gedruckt worden wäre, wenn Ihre Exception nicht behandelt worden wäre, nachdem sie bereits behandelt wurde. Das ist eine viel schwierigere Frage. Leider gibt sys.exc_info (None, None, None) wenn keine Ausnahme behandelt wird. Andere verwandte sys Attribute helfen ebenfalls nicht. sys.exc_traceback ist veraltet und nicht definiert, wenn keine Ausnahme behandelt wird. sys.last_traceback scheint perfekt zu sein, aber es scheint nur während interaktiver Sitzungen definiert zu sein.

Wenn Sie steuern können, wie die Ausnahme ausgelöst wird, können Sie möglicherweise inspect und eine benutzerdefinierte Ausnahme zum Speichern einiger Informationen verwenden. Aber ich bin mir nicht ganz sicher, wie das funktionieren würde.

Um die Wahrheit zu sagen, ist es eine ungewöhnliche Sache, eine Ausnahme zu fangen und zurückzugeben. Dies könnte ein Zeichen dafür sein, dass Sie sowieso umgestalten müssen.

example install

Gibt es ein Exception-Objekt (unbekannter Herkunft) gibt es Möglichkeit, seine Rückverfolgung zu erhalten? Ich habe Code wie folgt:

def stuff():
   try:
       .....
       return useful
   except Exception as e:
       return e

result = stuff()
if isinstance(result, Exception):
    result.traceback <-- How?

Wie kann ich das Traceback aus dem Exception-Objekt extrahieren, sobald ich es habe?




Es gibt einen guten Grund, warum das Traceback nicht in der Exception gespeichert ist. Da das Traceback Verweise auf die Locals seines Stacks enthält, würde dies zu einem zirkulären Verweis und einem (temporären) Speicherleck führen, bis der zirkuläre GC eintritt. (Deshalb sollten Sie das Traceback niemals in einer lokalen Variablen speichern .)

Das einzige, was ich mir vorstellen kann, wäre, dass Sie die Globals von monkeypatch so anpassen, dass es, wenn es denkt, dass es eine Exception abfängt, tatsächlich einen speziellen Typ abfängt und die Exception als Aufrufer an Sie weitergegeben wird:

module_containing_stuff.Exception = type("BogusException", (Exception,), {})
try:
    stuff()
except Exception:
    import sys
    print sys.exc_info()



Related

python debugging exception-handling