Ich habe eine Funktion, die vom Hauptprogramm aufgerufen wird:
try:
someFunction()
except:
print "exception happened!"
In der Mitte der Ausführung der Funktion wird jedoch eine Ausnahme ausgelöst, sodass zum except
Teil gesprungen wird .
Wie kann ich genau sehen, was in der passiert ist someFunction()
, das die Ausnahme verursacht hat?
except:
(ohne Bareraise
), außer vielleicht einmal pro Programm und vorzugsweise nicht dann.except
Klauseln verwenden, müssen Sie den Ausnahmetyp nicht überprüfen. Dies geschieht normalerweise, um einem bestimmten Ausnahmetyp entsprechend zu handeln.except
Blocks ist die Ausnahme über diesys.exc_info()
Funktion verfügbar. Diese Funktion gibt ein Tupel mit drei Werten zurück, die Informationen zu der Ausnahme enthalten, die derzeit behandelt wird.Antworten:
Die anderen Antworten weisen alle darauf hin, dass Sie keine generischen Ausnahmen abfangen sollten, aber niemand scheint Ihnen sagen zu wollen, warum. Dies ist wichtig, um zu verstehen, wann Sie die "Regel" brechen können. Hier ist eine Erklärung. Grundsätzlich ist es so, dass Sie sich nicht verstecken:
Solange Sie darauf achten, keines dieser Dinge zu tun, ist es in Ordnung, die generische Ausnahme abzufangen. Sie können dem Benutzer beispielsweise auf andere Weise Informationen über die Ausnahme bereitstellen, z.
Wie kann man also die generische Ausnahme abfangen? Es gibt verschiedene Möglichkeiten. Wenn Sie nur das Ausnahmeobjekt möchten, gehen Sie folgendermaßen vor:
Stellen Sie sicher, dass
message
der Benutzer auf eine kaum zu übersehende Weise darauf aufmerksam gemacht wird! Das Drucken wie oben gezeigt reicht möglicherweise nicht aus, wenn die Nachricht in vielen anderen Nachrichten vergraben ist. Wenn Sie die Aufmerksamkeit des Benutzers nicht auf sich ziehen, bedeutet dies, dass Sie alle Ausnahmen verschlucken. Wenn Sie nach dem Lesen der Antworten auf dieser Seite einen Eindruck hinterlassen sollten, ist dies keine gute Sache . Durch Beenden des Ausnahmeblocks mit einerraise
Anweisung wird das Problem behoben, indem die abgefangene Ausnahme transparent erneut ausgelöst wird.Der Unterschied zwischen dem oben Gesagten und der Verwendung
except:
ohne Argument ist zweifach:except:
gibt Ihnen nicht das Ausnahmeobjekt, das überprüft werden sollSystemExit
,KeyboardInterrupt
undGeneratorExit
werden nicht durch den oben genannten Code gefangen, die in der Regel ist das, was Sie wollen. Siehe die Ausnahmehierarchie .Wenn Sie auch denselben Stacktrace möchten, den Sie erhalten, wenn Sie die Ausnahme nicht abfangen, können Sie diesen wie folgt erhalten (immer noch in der Ausnahmeklausel enthalten):
Wenn Sie das
logging
Modul verwenden, können Sie die Ausnahme (zusammen mit einer Nachricht) wie folgt in das Protokoll drucken:Wenn Sie tiefer graben und den Stapel untersuchen, Variablen usw. betrachten möchten, verwenden Sie die
post_mortem
Funktion despdb
Moduls im Ausnahmeblock:Ich habe festgestellt, dass diese letzte Methode bei der Suche nach Fehlern von unschätzbarem Wert ist.
quelle
Rufen Sie den Namen der Klasse ab, zu der das Ausnahmeobjekt gehört:
Bei Verwendung der Funktion print_exc () wird auch die Stapelverfolgung gedruckt, die für jede Fehlermeldung von wesentlicher Bedeutung ist.
So was:
Sie erhalten folgende Ausgabe:
Und nach dem Drucken und Analysieren kann der Code entscheiden, keine Ausnahme zu behandeln und nur Folgendes auszuführen
raise
:Ausgabe:
Und Dolmetscher druckt Ausnahme:
Nach der
raise
ursprünglichen Ausnahme wird die Weitergabe des Aufrufstapels fortgesetzt. ( Vorsicht vor möglichen Gefahren ) Wenn Sie eine neue Ausnahme auslösen, wird eine neue (kürzere) Stapelspur erstellt.Ausgabe:
Beachten Sie, dass Traceback keine
calculate()
Funktion von Zeile enthält,9
die der Ursprung der ursprünglichen Ausnahme iste
.quelle
traceback.format_exc()
auche.__class__.__name__
Ist dies dasselbe wie intype(e).__name__
der obigen Antwort vorgeschlagen?Normalerweise sollten Sie nicht alle möglichen Ausnahmen abfangen,
try: ... except
da diese zu weit gefasst sind. Fangen Sie einfach diejenigen, von denen erwartet wird, dass sie aus irgendeinem Grund passieren. Wenn Sie dies wirklich müssen, z. B. wenn Sie beim Debuggen mehr über ein Problem erfahren möchten, sollten Sie dies tunquelle
try: ... except Exception:
viele Dinge, z. B. die Verwendung netzwerkabhängiger Bibliotheken oder eine Datenmasseurin, die möglicherweise seltsame Dinge an sie sendet. Natürlich habe ich auch die richtige Protokollierung. Dies ist entscheidend, damit das Programm im Falle eines einzelnen Fehlers in den Eingabedaten weiterarbeiten kann.smtplib
?Sofern
somefunction
es sich nicht um eine sehr schlecht codierte Legacy-Funktion handelt, sollten Sie nicht das benötigen, was Sie verlangen.Verwenden Sie mehrere
except
Klauseln, um verschiedene Ausnahmen auf unterschiedliche Weise zu behandeln:Der Hauptpunkt ist, dass Sie keine generische Ausnahme abfangen sollten, sondern nur die, die Sie benötigen. Ich bin sicher, dass Sie keine unerwarteten Fehler oder Bugs beschatten möchten.
quelle
Die meisten Antworten verweisen
except (…) as (…):
(zu Recht) auf die Syntax, aber gleichzeitig möchte niemand über einen Elefanten in dem Raum sprechen, in dem der Elefantsys.exc_info()
funktioniert. Aus der Dokumentation des sys- Moduls (Schwerpunkt Mine):Ich denke, das
sys.exc_info()
könnte als die direkteste Antwort auf die ursprüngliche Frage behandelt werden: Woher weiß ich, welche Art von Ausnahme aufgetreten ist?quelle
except
. Der Vollständigkeit halberexctype, value = sys.exc_info()[:2]
wird Ihnen der Ausnahmetyp mitgeteilt, der dann auf dem verwendet werden kannexcept
.try: someFunction () außer Exception, exc:
quelle
exc.__class__.__name__
wurde bereits in Alex 'Antwort vorgeschlagen - stackoverflow.com/a/9824060/95735Diese Antworten eignen sich gut zum Debuggen, aber zum programmgesteuerten Testen der Ausnahme
isinstance(e, SomeException)
können sie nützlich sein, da sie auch auf Unterklassen von testenSomeException
, sodass Sie Funktionen erstellen können, die für Hierarchien von Ausnahmen gelten.quelle
So gehe ich mit meinen Ausnahmen um. Die Idee ist, das Problem zu lösen, wenn dies einfach ist, und später, wenn möglich, eine wünschenswertere Lösung hinzuzufügen. Lösen Sie das Problem nicht in dem Code, der die Ausnahme generiert, oder dieser Code verliert den Überblick über den ursprünglichen Algorithmus, der auf den Punkt geschrieben werden sollte. Übergeben Sie jedoch, welche Daten zur Lösung des Problems benötigt werden, und geben Sie ein Lambda zurück, falls Sie das Problem nicht außerhalb des Codes lösen können, der es generiert.
Im Moment habe ich keine komplizierten Lösungen hinzugefügt, da ich nicht tangential zum Zweck meiner App denken möchte. Wenn ich in Zukunft mehr über mögliche Lösungen weiß (da die App mehr entwickelt wurde), könnte ich ein Wörterbuch mit Lösungen hinzufügen, die von indiziert werden
during
.In dem gezeigten Beispiel könnte eine Lösung darin bestehen, nach App-Daten zu suchen, die an einer anderen Stelle gespeichert sind, beispielsweise wenn die Datei 'app.p' versehentlich gelöscht wurde.
Da das Schreiben des Ausnahmehandlers keine kluge Idee ist (wir kennen die besten Lösungsmöglichkeiten noch nicht, da sich das App-Design weiterentwickeln wird), geben wir einfach die einfache Lösung zurück, die sich so verhält, als würden wir ausgeführt die App zum ersten Mal (in diesem Fall).
quelle
Um Lauritz 'Antwort zu ergänzen, habe ich einen Dekorator / Wrapper für die Ausnahmebehandlung erstellt und der Wrapper protokolliert, welcher Ausnahmetyp aufgetreten ist.
Dies kann für eine Klassenmethode oder eine eigenständige Funktion mit dem Dekorator aufgerufen werden:
@general_function_handler
Das vollständige Beispiel finden Sie in meinem Blog über: http://ryaneirwin.wordpress.com/2014/05/31/python-decorators-and-exception-handling/
quelle
Sie können wie von Lauritz empfohlen beginnen mit:
und dann einfach so zu
print ex
mögen:quelle
Die eigentliche Ausnahme kann folgendermaßen erfasst werden:
Weitere Informationen zu Ausnahmen finden Sie im Python-Tutorial .
quelle
Ihre Frage lautet: "Wie kann ich genau sehen, was in someFunction () passiert ist, das die Ausnahme verursacht hat?"
Es scheint mir, dass Sie nicht fragen, wie Sie mit unvorhergesehenen Ausnahmen im Produktionscode umgehen sollen (wie viele Antworten angenommen haben), sondern wie Sie herausfinden, was eine bestimmte Ausnahme während der Entwicklung verursacht.
Am einfachsten ist es, einen Debugger zu verwenden, der dort anhalten kann, wo die nicht erfasste Ausnahme auftritt, vorzugsweise nicht beendet wird, damit Sie die Variablen überprüfen können. Dies kann beispielsweise PyDev in der Open Source-IDE von Eclipse. Um dies in Eclipse zu aktivieren, öffnen Sie die Debug-Perspektive, wählen Sie
Manage Python Exception Breakpoints
imRun
Menü aus und überprüfen SieSuspend on uncaught exceptions
.quelle
Vermeiden Sie es einfach, die Ausnahme abzufangen, und der Traceback, den Python druckt, zeigt Ihnen, welche Ausnahme aufgetreten ist.
quelle