Was ist der beste Weg, um Ausnahmemeldungen von Komponenten der Standardbibliothek in Python abzurufen?
Mir ist aufgefallen, dass Sie es in einigen Fällen über ein message
Feld wie das folgende erhalten können:
try:
pass
except Exception as ex:
print(ex.message)
In einigen Fällen (z. B. bei Socket-Fehlern) müssen Sie jedoch Folgendes tun:
try:
pass
except socket.error as ex:
print(ex)
Ich habe mich gefragt, ob es einen Standardweg gibt, um die meisten dieser Situationen abzudecken.
python
exception
exception-handling
Gefrorenes Herz
quelle
quelle
except Foo as bar:
ist dasselbe wieexcept Foo, bar:
(außer dass das erstere neuer ist und in 3.x weiterhin funktioniert), ob der Fehler mit einemmessage
Attribut kommt oder nicht, ist getrennt..message
auf einen Fehler Standard ist oder nicht?print(msg)
ist nur eine Abkürzung fürprint(str(msg))
message
ist veraltet.Antworten:
Wenn Sie sich die Dokumentation für die integrierten Fehler ansehen , werden Sie feststellen, dass die meisten
Exception
Klassen ihr erstes Argument alsmessage
Attribut zuweisen . Nicht alle von ihnen tun dies jedoch.Insbesondere
EnvironmentError
(mit UnterklassenIOError
undOSError
) hat ein erstes Argument vonerrno
, das zweite vonstrerror
. Es gibt keinmessage
...strerror
ist ungefähr analog zu dem, was normalerweise ein wäremessage
.Im Allgemeinen können Unterklassen von
Exception
tun, was sie wollen. Sie können einmessage
Attribut haben oder nicht . Zukünftige integrierteException
s haben möglicherweise keinmessage
Attribut. JedeException
Unterklasse importiert von Bibliotheken von Drittanbietern oder Benutzercode möglicherweise nicht über einemessage
Attribut.Ich denke, der richtige Weg, dies zu handhaben, besteht darin, die spezifischen
Exception
Unterklassen zu identifizieren, die Sie abfangen möchten, und dann nur diejenigen anstelle von allem mit einemexcept Exception
abzufangen und dann die Attribute zu verwenden, die diese bestimmte Unterklasse definiert, wie Sie möchten.Wenn Sie
print
etwas müssen , denke ich, dass das Drucken des gefangenenException
selbst höchstwahrscheinlich das tut, was Sie wollen, unabhängig davon, ob es einmessage
Attribut hat oder nicht.Sie können auch nach dem Nachrichtenattribut suchen, wenn Sie dies möchten, aber ich würde es nicht wirklich vorschlagen, da es nur chaotisch erscheint:
try: pass except Exception as e: # Just print(e) is cleaner and more likely what you want, # but if you insist on printing message specifically whenever possible... if hasattr(e, 'message'): print(e.message) else: print(e)
quelle
str(ex)
anstatt nur zu verwendenex
?print()
ruft automatischstr()
nach Ihnen. Es gibt keinen Grund, es manuell aufzurufen, obwohl es harmlos ist, da das Aufrufenstr()
einer Zeichenfolge nur die Zeichenfolge selbst zurückgibt.str()
wenn die Nachricht vom Typ istunicode
.Um die Antwort von @artofwarfare zu verbessern, halte ich Folgendes für eine bessere Möglichkeit, nach dem
message
Attribut zu suchen und es zu drucken oder dasException
Objekt als Fallback zu drucken .try: pass except Exception as e: print getattr(e, 'message', repr(e))
Der Aufruf von
repr
ist optional, aber ich finde es in einigen Anwendungsfällen notwendig.Update Nr. 1:
Nach dem Kommentar von @MadPhysicist finden Sie hier einen Beweis dafür, warum der Aufruf von
repr
möglicherweise erforderlich ist. Versuchen Sie, den folgenden Code in Ihrem Interpreter auszuführen:try: raise Exception except Exception as e: print(getattr(e, 'message', repr(e))) print(getattr(e, 'message', str(e)))
Update Nr. 2:
Hier ist eine Demo mit Besonderheiten für Python 2.7 und 3.5: https://gist.github.com/takwas/3b7a6edddef783f2abddffda1439f533
quelle
getattr
löst eine Ausnahme aus, wenn das übergebene Objekt nicht das angeforderte Attribut hat. Wenn Sie so etwas tun wollten, sollten Sie das optionale dritte Argument fürgetattr
Folgendes verwenden :print getattr(e, 'message', e)
. Zweifellos besser als das, was ich getan habe. Eine andere Option wäreprint(e.message if hasattr(e, 'message') else e)
.str
stattdessen wollenrepr
.str
,repr
fügt nur die Klassennamen. Anstatt zu verwendenrepr
, würde ich vorschlagen, zu verwendenprint('{e.__class__.__name__}: {e}'.format(e=e))
. Die Druckausgabe ist sauberer und entspricht der Ausgabe von Raise selbst.'{e.__class__.__module__}.{e.__class__.__name__}: {e}'
repr(e)
war vorerst die einzige Lösung, die mir geholfen hat, mindestens eine minimale Menge an Informationen über einen Fehler zu drucken, den ich unter bestimmten Umständen festgestellt habe.repr(e)
ergibtKeyError(0,)
(was der Fehler ist), währendstr(e)
odere.message
nur0
oder gar nichts ergab .Ich hatte das gleiche Problem. Ich denke, die beste Lösung ist die Verwendung von log.exception, die automatisch die Stapelverfolgung und die Fehlermeldung ausgibt, wie z.
try: pass log.info('Success') except: log.exception('Failed')
quelle
log
? Ich habe geradeimport log
Python 2.7.13 ausprobiert und die Meldung erhalten, dass es kein Modul mit diesem Namen gibt. Ist es etwas, das Sie über hinzugefügt haben,pip
oder wurde es in einer neueren Version von Python hinzugefügt (ich weiß, ich weiß, ich muss auf Python 3 aktualisieren ... Ich werde das tun, sobald CentOS standardmäßig nicht mehr mit Python 2 ausgeliefert wird ...)import logging
\ nlog = logging.getLogger(__name__)
Ich hatte auch das gleiche Problem. Als ich mich damit befasste, stellte ich fest, dass die Exception-Klasse ein
args
Attribut hat, das die Argumente erfasst, die zum Erstellen der Ausnahme verwendet wurden. Wenn Sie die Ausnahmen eingrenzen, die mit Ausnahme einer Teilmenge abgefangen werden, sollten Sie bestimmen können, wie sie erstellt wurden und welches Argument die Nachricht enthält.try: # do something that may raise an AuthException except AuthException as ex: if ex.args[0] == "Authentication Timeout.": # handle timeout else: # generic handling
quelle