Ich habe diesen try
-Block in meinem Code:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise ValueError(errmsg)
Streng genommen ziehe ich eine andereValueError
an, nicht die von do_something...()
geworfene ValueError
, die in diesem Fall als err
bezeichnet wird. Wie füge ich eine benutzerdefinierte Nachricht an err
an? Ich versuche den folgenden Code, schlägt jedoch fehl, weil err
, eine ValueError
Instanz nicht aufgerufen werden kann:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise err(errmsg)
Update: Für Python 3 überprüfen Sie Bens Antwort
So hängen Sie eine Nachricht an die aktuelle Ausnahme an und rufen sie erneut auf: (Der äußere Versuch/die Ausnahme ist nur zur Darstellung des Effekts)
Für Python 2.x mit x> = 6:
try:
try:
raise ValueError # something bad...
except ValueError as err:
err.message=err.message+" hello"
raise # re-raise current exception
except ValueError as e:
print(" got error of type "+ str(type(e))+" with message " +e.message)
Dies wird auch das richtige tun , wenn err
abgeleitet von ValueError
ist. Zum Beispiel UnicodeDecodeError
.
Beachten Sie, dass Sie err
hinzufügen können, was Sie möchten. Zum Beispiel err.problematic_array=[1,2,3]
.
Edit: @Ducan Punkte in einem Kommentar, das oben nicht mit Python 3 funktioniert, da .message
kein Mitglied von ValueError
ist. Stattdessen können Sie Folgendes verwenden (gültiger Python 2.6 oder höher oder 3.x):
try:
try:
raise ValueError
except ValueError as err:
if not err.args:
err.args=('',)
err.args = err.args + ("hello",)
raise
except ValueError as e:
print(" error was "+ str(type(e))+str(e.args))
Edit2:
Je nach Zweck können Sie die zusätzlichen Informationen auch unter Ihrem eigenen Variablennamen hinzufügen. Für beide, Python2 und Python3:
try:
try:
raise ValueError
except ValueError as err:
err.extra_info = "hello"
raise
except ValueError as e:
print(" error was "+ str(type(e))+str(e))
if 'extra_info' in dir(e):
print e.extra_info
Mir ist klar, dass diese Frage schon eine Weile existiert, aber wenn Sie nur Python 3.x unterstützen, wird dies wirklich eine schöne Sache :)
Wir können die Ausnahmen mit raise von verketten.
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks') from e
In diesem Fall hat die Ausnahme, die Ihr Anrufer auffangen würde, die Leitungsnummer des Ortes, an dem wir unsere Ausnahme melden.
Traceback (most recent call last):
File "test.py", line 2, in <module>
1 / 0
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "test.py", line 4, in <module>
raise Exception('Smelly socks') from e
Exception: Smelly socks
Beachten Sie, dass die untere Ausnahme nur den Stacktrace enthält, von dem aus wir die Ausnahme ausgelöst haben. Ihr Anrufer könnte trotzdem die ursprüngliche Ausnahme erhalten, indem er auf das __cause__
-Attribut der Ausnahme zugreifen, die er abfängt.
Oder Sie können with_traceback verwenden.
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks').with_traceback(e.__traceback__)
Bei Verwendung dieses Formulars hat die Ausnahme, die Ihr Aufrufer abfangen würde, das Traceback, ab dem der ursprüngliche Fehler aufgetreten ist.
Traceback (most recent call last):
File "test.py", line 2, in <module>
1 / 0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 4, in <module>
raise Exception('Smelly socks').with_traceback(e.__traceback__)
File "test.py", line 2, in <module>
1 / 0
Exception: Smelly socks
Beachten Sie, dass die untere Ausnahme die Zeile hat, in der wir die ungültige Division durchgeführt haben, sowie die Zeile, in der wir die Ausnahme erneut erhöhen.
try:
try:
int('a')
except ValueError as e:
raise ValueError('There is a problem: {0}'.format(e))
except ValueError as err:
print err
druckt:
There is a problem: invalid literal for int() with base 10: 'a'
Es scheint, dass alle Antworten Informationen zu e.args [0] hinzufügen, wodurch die vorhandene Fehlermeldung geändert wird. Gibt es einen Nachteil bei der Erweiterung des args-Tupels? Ich denke, der mögliche Nachteil besteht darin, dass Sie die ursprüngliche Fehlernachricht für Fälle lassen können, in denen eine Analyse der Zeichenfolge erforderlich ist. Sie könnten dem Tuple mehrere Elemente hinzufügen, wenn Ihre benutzerdefinierte Fehlerbehandlung mehrere Meldungen oder Fehlercodes erzeugt hat, für den Fall, dass das Traceback programmgesteuert analysiert werden würde (wie über ein Systemüberwachungstool).
## Approach #1, if the exception may not be derived from Exception and well-behaved:
def to_int(x):
try:
return int(x)
except Exception as e:
e.args = (e.args if e.args else Tuple()) + ('Custom message',)
raise
>>> to_int('12')
12
>>> to_int('12 monkeys')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in to_int
ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message')
oder
## Approach #2, if the exception is always derived from Exception and well-behaved:
def to_int(x):
try:
return int(x)
except Exception as e:
e.args += ('Custom message',)
raise
>>> to_int('12')
12
>>> to_int('12 monkeys')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in to_int
ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message')
Sehen Sie einen Nachteil dieses Ansatzes?
Mit dieser Codevorlage können Sie eine Ausnahme mit einer benutzerdefinierten Nachricht auslösen.
try:
raise ValueError
except ValueError as err:
raise type(err)("my message")
Dies ist die Funktion, die ich zum Ändern der Ausnahmemeldung in Python 2.7 und 3.x verwende, während der ursprüngliche Traceback beibehalten wird. Es erfordert six
def reraise_modify(caught_exc, append_msg, prepend=False):
"""Append message to exception while preserving attributes.
Preserves exception class, and exception traceback.
Note:
This function needs to be called inside an except because
`sys.exc_info()` requires the exception context.
Args:
caught_exc(Exception): The caught exception object
append_msg(str): The message to append to the caught exception
prepend(bool): If True prepend the message to args instead of appending
Returns:
None
Side Effects:
Re-raises the exception with the preserved data / trace but
modified message
"""
ExceptClass = type(caught_exc)
# Keep old traceback
traceback = sys.exc_info()[2]
if not caught_exc.args:
# If no args, create our own Tuple
arg_list = [append_msg]
else:
# Take the last arg
# If it is a string
# append your message.
# Otherwise append it to the
# arg list(Not as pretty)
arg_list = list(caught_exc.args[:-1])
last_arg = caught_exc.args[-1]
if isinstance(last_arg, str):
if prepend:
arg_list.append(append_msg + last_arg)
else:
arg_list.append(last_arg + append_msg)
else:
arg_list += [last_arg, append_msg]
caught_exc.args = Tuple(arg_list)
six.reraise(ExceptClass,
caught_exc,
traceback)
Rufen Sie entweder die neue Ausnahme mit der Fehlermeldung auf
raise Exception('your error message')
oder
raise ValueError('your error message')
an der Stelle, an der Sie die Meldung OR ausführen möchten, fügen Sie die Fehlernachricht mit "from" in die aktuelle Ausnahme ein:
except ValueError as e:
raise ValueError('your message') from e
In Python 3 integrierte Ausnahmen haben das Feld strerror
:
except ValueError as err:
err.strerror = "New error message"
raise err
Die aktuelle Antwort funktionierte nicht gut für mich. Wenn die Ausnahme nicht erneut abgefangen wird, wird die angefügte Nachricht nicht angezeigt.
Wenn Sie jedoch wie unten vorgehen, wird die Ablaufverfolgung beibehalten und die angefügte Nachricht angezeigt, unabhängig davon, ob die Ausnahme erneut abgefangen wird oder nicht.
try:
raise ValueError("Original message")
except ValueError as err:
t, v, tb = sys.exc_info()
raise t, ValueError(err.message + " Appended Info"), tb
(Ich habe Python 2.7 verwendet, habe es nicht in Python 3 ausprobiert)