J'ai ce bloc try
dans mon code:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise ValueError(errmsg)
À proprement parler, je soulève en fait une autreValueError
, pas la ValueError
levée par do_something...()
, désignée par err
dans ce cas. Comment attacher un message personnalisé à err
? J'essaie le code suivant mais échoue à cause de err
, une ValueError
instance , n'étant pas appelable:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise err(errmsg)
Mise à jour: Pour Python 3, vérifiez Réponse de Ben
Pour attacher un message à l'exception actuelle et le relancer: (Le test externe/except est juste pour montrer l'effet)
Pour python 2.x où 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)
Cela fera également le bon choix si err
est dérivé de ValueError
. Par exemple UnicodeDecodeError
.
Notez que vous pouvez ajouter ce que vous voulez à err
. Par exemple err.problematic_array=[1,2,3]
.
Edit: @Ducan pointe dans un commentaire, ce qui précède ne fonctionne pas avec python 3 car .message
n'est pas membre de ValueError
. À la place, vous pouvez utiliser ceci (Python 2.6 ou version ultérieure ou 3.x valide):
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:
En fonction de l'objectif, vous pouvez également opter pour l'ajout d'informations supplémentaires sous votre propre nom de variable. Pour Python2 et 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
Je me rends compte que cette question existe depuis un certain temps, mais une fois que vous avez la chance de ne supporter que python 3.x, cela devient vraiment une chose de beauté :)
Nous pouvons chaîner les exceptions en utilisant raise from .
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks') from e
Dans ce cas, l'exception que votre appelant capturerait aurait le numéro de ligne de l'endroit où nous levons notre exception.
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
Notez que l’exception du bas n’a que le stacktrace à partir duquel nous avons levé notre exception. Votre appelant peut toujours obtenir l'exception d'origine en accédant à l'attribut __cause__
de l'exception capturée.
Ou vous pouvez utiliser with_traceback .
try:
1 / 0
except ZeroDivisionError as e:
raise Exception('Smelly socks').with_traceback(e.__traceback__)
À l'aide de ce formulaire, l'exception que votre appelant prendrait a la trace à partir de laquelle l'erreur d'origine s'est produite.
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
Remarquez que l’exception du bas a la ligne sur laquelle nous avons effectué la division non valide ainsi que la ligne sur laquelle nous relançons l’exception.
try:
try:
int('a')
except ValueError as e:
raise ValueError('There is a problem: {0}'.format(e))
except ValueError as err:
print err
impressions:
There is a problem: invalid literal for int() with base 10: 'a'
Il semble que toutes les réponses ajoutent des informations à e.args [0], modifiant ainsi le message d'erreur existant. Y a-t-il un inconvénient à étendre l'argument Tuple à la place? Je pense que l’avantage possible est que vous pouvez laisser le message d’erreur original seul dans les cas où l’analyse de cette chaîne est nécessaire; et vous pouvez ajouter plusieurs éléments au tuple si votre traitement d'erreur personnalisé génère plusieurs messages ou codes d'erreur, dans les cas où le suivi est analysé par programme (comme via un outil de surveillance du système).
## 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')
ou
## 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')
Pouvez-vous voir un inconvénient à cette approche?
Ce modèle de code devrait vous permettre de déclencher une exception avec un message personnalisé.
try:
raise ValueError
except ValueError as err:
raise type(err)("my message")
C'est la fonction que j'utilise pour modifier le message d'exception dans Python 2.7 et 3.x tout en préservant le suivi d'origine. Il nécessite 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)
Soit soulever la nouvelle exception avec votre message d'erreur en utilisant
raise Exception('your error message')
ou
raise ValueError('your error message')
à l’endroit où vous voulez le lever OR joindre le message d’erreur (remplacer) à l’exception courante en utilisant 'from':
except ValueError as e:
raise ValueError('your message') from e
Les exceptions intégrées à Python 3 ont le champ strerror
:
except ValueError as err:
err.strerror = "New error message"
raise err
La réponse actuelle ne fonctionne pas bien pour moi. Si l'exception n'est pas capturée à nouveau, le message ajouté ne s'affiche pas.
Cependant, faire comme ci-dessous conserve la trace et affiche le message ajouté, que l'exception soit ou non capturée à nouveau.
try:
raise ValueError("Original message")
except ValueError as err:
t, v, tb = sys.exc_info()
raise t, ValueError(err.message + " Appended Info"), tb
(J'ai utilisé Python 2.7, je ne l'ai pas essayé dans Python 3)