pyplot - title plt python
¿Cómo elevo la misma excepción con un mensaje personalizado en Python? (10)
Tengo este bloque de try
en mi código:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = ''My custom error message.''
raise ValueError(errmsg)
Estrictamente hablando, en realidad estoy levantando otro ValueError
, no el ValueError
arrojado por do_something...()
, que en este caso se conoce como err
. ¿Cómo adjunto un mensaje personalizado para err
? Intento el siguiente código pero falla debido a err
, una instancia de ValueError
, no se puede llamar:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = ''My custom error message.''
raise err(errmsg)
Actualización: para Python 3, revisa la respuesta de Ben
Para adjuntar un mensaje a la excepción actual y volver a subirlo: (el intento externo / solo es para mostrar el efecto)
Para python 2.x donde 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)
Esto también hará lo correcto si err
se deriva de ValueError
. Por ejemplo UnicodeDecodeError
.
Tenga en cuenta que puede agregar lo que quiera para err
. Por ejemplo err.problematic_array=[1,2,3]
.
Editar: puntos @Ducan en un comentario, lo anterior no funciona con python 3 ya que .message
no es miembro de ValueError
. En su lugar, puede usar esto (pitón válido 2.6 o posterior o 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:
Dependiendo de cuál sea el propósito, también puede optar por agregar la información adicional bajo su propio nombre de variable. Para python2 y 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
Esta es la función que uso para modificar el mensaje de excepción en Python 2.7 y 3.x conservando el rastreo original. Requiere 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)
Esta plantilla de código debería permitirle plantear una excepción con un mensaje personalizado.
try:
raise ValueError
except ValueError as err:
raise type(err)("my message")
La respuesta actual no me funcionó, si la excepción no se vuelve a capturar, no se muestra el mensaje adjunto.
Pero al hacer lo que sigue, ambos mantienen la traza y muestran el mensaje anexo, independientemente de si se vuelve a capturar la excepción o no.
try:
raise ValueError("Original message")
except ValueError as err:
t, v, tb = sys.exc_info()
raise t, ValueError(err.message + " Appended Info"), tb
(Utilicé Python 2.7, no lo intenté en Python 3)
Las excepciones integradas de Python 3 tienen el campo strerror
:
except ValueError as err:
err.strerror = "New error message"
raise err
Me doy cuenta de que esta pregunta ha existido por un tiempo, pero una vez que tienes la suerte de solo admitir Python 3.x, esto realmente se convierte en algo de belleza :)
elevar de
Podemos encadenar las excepciones usando raise from .
try:
1 / 0
except ZeroDivisionError as e:
raise Exception(''Smelly socks'') from e
En este caso, la excepción que atrapará la persona que llama tiene el número de línea del lugar donde presentamos nuestra excepción.
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
Observe que la excepción inferior solo tiene la pila desde donde levantamos nuestra excepción. Su interlocutor aún podría obtener la excepción original accediendo al atributo __cause__
de la excepción que __cause__
.
with_traceback
O puede usar with_traceback .
try:
1 / 0
except ZeroDivisionError as e:
raise Exception(''Smelly socks'').with_traceback(e.__traceback__)
Al usar este formulario, la excepción que captará su interlocutor tiene el rastreo desde donde se produjo el error original.
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
Observe que la excepción inferior tiene la línea en la que realizamos la división no válida, así como también la línea donde volvemos a publicar la excepción.
O sube la nueva excepción con tu mensaje de error usando
raise Exception(''your error message'')
o
raise ValueError(''your error message'')
dentro del lugar donde desea subirlo O adjunte (reemplace) el mensaje de error a la excepción actual usando ''de'':
except ValueError as e:
raise ValueError(''your message'') from e
Parece que todas las respuestas están agregando información a e.args [0], lo que altera el mensaje de error existente. ¿Hay algún inconveniente en extender la tupla args en su lugar? Creo que la posible ventaja es que puedes dejar el mensaje de error original solo para los casos en que se necesita analizar esa cadena; y podría agregar múltiples elementos a la tupla si su manejo de error personalizado produjo varios mensajes o códigos de error, para los casos en que la trazabilidad sería analizada programáticamente (como a través de una herramienta de monitoreo del sistema).
## 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'')
o
## 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'')
¿Puedes ver una desventaja de este enfoque?
si desea personalizar el tipo de error, una cosa simple que puede hacer es definir una clase de error basada en ValueError.
try:
try:
int(''a'')
except ValueError as e:
raise ValueError(''There is a problem: {0}''.format(e))
except ValueError as err:
print err
huellas dactilares:
There is a problem: invalid literal for int() with base 10: ''a''