Die Antwort auf diese Frage hängt von der verwendeten Python-Version ab.
In Python 3
Es ist ganz einfach: Ausnahmen sind mit einem __traceback__
Attribut ausgestattet, das den Traceback enthält. Dieses Attribut ist auch beschreibbar und kann bequem mithilfe der with_traceback
Ausnahmemethode festgelegt werden:
raise Exception("foo occurred").with_traceback(tracebackobj)
Diese Funktionen werden in der raise
Dokumentation nur minimal beschrieben .
Alle Gutschriften für diesen Teil der Antwort sollten an Vyctor gehen, der diese Informationen zuerst veröffentlicht hat . Ich füge es hier nur ein, weil diese Antwort oben feststeckt und Python 3 immer häufiger wird.
In Python 2
Es ist ärgerlich komplex. Das Problem mit Tracebacks ist, dass sie Verweise auf Stapelrahmen haben und Stapelrahmen Verweise auf die Rückverfolgungen haben, die Verweise auf Stapelrahmen haben , die Verweise auf ... Sie haben die Idee. Dies verursacht Probleme für den Garbage Collector. (Vielen Dank an ecatmur für den ersten Hinweis.)
Die gute Möglichkeit, dies zu lösen, besteht darin , den Zyklus nach dem Verlassen der except
Klausel chirurgisch zu unterbrechen, wie es 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 except
Klausel funktioniert . Es gibt ein Tupel zurück, das die Ausnahme, den Ausnahmetyp und den Traceback für jede Ausnahme enthält, die gerade behandelt wird.
Wenn Sie sich also innerhalb der except
Klausel befinden, können Sie die Ausgabe von sys.exc_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
Wie aus Ihrer Bearbeitung hervorgeht, versuchen Sie jedoch, den Traceback abzurufen, der gedruckt worden wäre, wenn Ihre Ausnahme nicht behandelt worden wäre, nachdem sie bereits behandelt wurde. Das ist eine viel schwierigere Frage. Leider sys.exc_info
gibt , (None, None, None)
wenn keine Ausnahme behandelt wird. Andere verwandte sys
Attribute helfen auch nicht. sys.exc_traceback
ist veraltet und undefiniert, wenn keine Ausnahme behandelt wird; sys.last_traceback
scheint perfekt zu sein, scheint aber nur während interaktiver Sitzungen definiert zu werden.
Wenn Sie steuern können, wie die Ausnahme ausgelöst wird, können Sie möglicherweise inspect
eine benutzerdefinierte Ausnahme verwenden , um einige der Informationen zu speichern. Aber ich bin mir nicht ganz sicher, wie das funktionieren würde.
Um die Wahrheit zu sagen, ist es ungewöhnlich, eine Ausnahme zu fangen und zurückzugeben. Dies könnte ein Zeichen dafür sein, dass Sie ohnehin umgestalten müssen.