Ich weiß, dass ich, wenn ich eine Ausnahme erneut auslösen möchte, einfach raise
ohne Argumente im jeweiligen except
Block verwende. Aber gegeben ein verschachtelter Ausdruck wie
try:
something()
except SomeError as e:
try:
plan_B()
except AlsoFailsError:
raise e # I'd like to raise the SomeError as if plan_B()
# didn't raise the AlsoFailsError
Wie kann ich das erneut erhöhen, SomeError
ohne die Stapelspur zu unterbrechen? raise
allein würde in diesem Fall die neueren wieder erhöhen AlsoFailsError
. Oder wie könnte ich meinen Code umgestalten, um dieses Problem zu vermeiden?
plan_B
andere Funktion einzufügen, dieTrue
auf Erfolg undFalse
Ausnahme zurückgreift? Dann könnte der äußereexcept
Block einfach seinif not try_plan_B(): raise
arg
und ich würde versuchen , Berufung ,arg.plan_B()
die ein erhöhen könnteAttributeError
aufgrundarg
keinen Plan B bereitstelltplan_B
AusnahmenAntworten:
Ab Python 3 wird der Traceback in der Ausnahme gespeichert, sodass ein einfacher
raise e
das (meistens) Richtige tut:Der erzeugte Traceback enthält einen zusätzlichen Hinweis,
SomeError
der während der Bearbeitung aufgetreten istAlsoFailsError
(weilraise e
er sich im Inneren befindetexcept AlsoFailsError
). Dies ist irreführend, da das, was tatsächlich passiert ist, umgekehrt ist - wir sind darauf gestoßenAlsoFailsError
und haben es gehandhabt, während wir versucht haben, uns davon zu erholenSomeError
.AlsoFailsError
Ersetzen Sieraise e
durch, um einen Traceback zu erhalten, der nicht enthalten istraise e from None
.In Python 2 speichern Sie den Ausnahmetyp, den Wert und den Traceback in lokalen Variablen und verwenden die Form mit drei Argumenten
raise
:quelle
raise self.exc_info[1], None, self.exc_info[2]
nachdemself.exc_info = sys.exc_info()
-[1]
aus irgendeinem Grund auf den ersten Platz gebrachtraise t, None, tb
verliert den Wert der Ausnahme und erzwingt eineraise
erneute Instanziierung des Typs, wodurch Sie einen weniger spezifischen (oder einfach falschen) Ausnahmewert erhalten. Wenn es sich beispielsweise um eine ausgelöste Ausnahme handeltKeyError("some-key")
, wird sie nur erneut ausgelöstKeyError()
und der exakt fehlende Schlüssel aus dem Traceback weggelassen.raise v.with_traceback(tb)
. (Ihr Kommentar sagt sogar so viel, außer es schlägt vor, den Wert erneut zu instanziieren.)sys.exc_info()
in einer lokalen Variablen zu speichern, war vor Python 2.0 (veröffentlicht vor 13 Jahren) sinnvoll, grenzt aber heute an Lächerlichkeit. Modernes Python wäre ohne den Zykluskollektor nahezu nutzlos, da jede nicht triviale Python-Bibliothek Zyklen ohne Pause erstellt und von ihrer korrekten Bereinigung abhängt.Selbst wenn die akzeptierte Lösung richtig ist, ist es gut, auf die Six- Bibliothek zu verweisen, die eine Python 2 + 3-Lösung verwendet
six.reraise
.Sie können also schreiben:
quelle
six.raise_from
wenn Sie von Sechs sprechen, können Sie ihn auch verwenden, wenn Sie Informationen einschließen möchten, dieplan_B()
ebenfalls fehlgeschlagen sind.six.raise_from
Sie eine neue Ausnahme erstellen, die mit einer vorherigen verknüpft ist, werden Sie nicht erneut ausgelöst , sodass die Rückverfolgung anders ist.reraise
den Eindruck bekommen nursomething()
warfSomeError
, wenn Sieraise_from
auch wissen , dass dies verursachtplan_B()
ausgeführt werden, aber das wirftAlsoFailsError
. Es kommt also auf den Anwendungsfall an. Ich denke,raise_from
wird das Debuggen einfacher machenWie pro Drew McGowen Vorschlag , sondern von einem allgemeinen Fall (wo ein Rückgabewert die Pflege
s
vorhanden ist), hier ist eine Alternative zu user4815162342 Antwort :quelle
raise from
, würde der Stack-Trace mich auch dazu bringen, Plan B fehlgeschlagen zu sehen. Was übrigens in Python 2 emuliert werden kann.Python 3.5+ hängt die Traceback-Informationen ohnehin an den Fehler an, sodass es nicht mehr erforderlich ist, sie separat zu speichern.
quelle
except
. Aber du hast Recht, wenn ich ersetzenerr = e
durch, sagen sie,raise AttributeError
erhalten Sie zunächst denSyntaxError
Stack - Trace, gefolgt von einemDuring handling of the above exception, another exception occurred:
und denAttributeError
Stack - Trace. Gut zu wissen, obwohl man sich leider nicht darauf verlassen kann, dass 3.5+ installiert wird. PS: ff verstehen nicht-Deutsche Schwierigkeiten nicht;)