Quiero lograr algo como esto:
def foo():
try:
raise IOError('Stuff ')
except:
raise
def bar(arg1):
try:
foo()
except Exception as e:
e.message = e.message + 'happens at %s' % arg1
raise
bar('arg1')
Traceback...
IOError('Stuff Happens at arg1')
Pero lo que obtengo es:
Traceback..
IOError('Stuff')
¿Alguna pista sobre cómo lograr esto? ¿Cómo hacerlo tanto en Python 2 como en 3?
message
atributo Exception , encontré esta pregunta SO, BaseException.message en desuso en Python 2.6 , que parece indicar que su uso ahora está desaconsejado (y por qué no está en los documentos).Respuestas:
Lo haría así, así que cambiar su tipo
foo()
no requerirá también cambiarlobar()
.Actualización 1
Aquí hay una ligera modificación que conserva el rastreo original:
Actualización 2
Para Python 3.x, el código en mi primera actualización es sintácticamente incorrecto y la idea de tener un
message
atributo activadoBaseException
se retractó en un cambio a PEP 352 el 16/05/2012 (mi primera actualización se publicó el 12/03/2012) . Entonces, actualmente, en Python 3.5.2 de todos modos, necesitaría hacer algo en este sentido para preservar el rastreo y no codificar el tipo de excepción en la funciónbar()
. También tenga en cuenta que habrá la línea:en los mensajes de rastreo que se muestran.
Actualización 3
Un comentarista preguntó si había una manera que funcione tanto en Python 2 y 3. Aunque la respuesta podría parecer que es "No", debido a las diferencias de sintaxis, no es una forma de evitar que mediante el uso de una función de ayuda al igual que
reraise()
en elsix
Agregar- en el módulo Entonces, si prefiere no usar la biblioteca por alguna razón, a continuación se muestra una versión independiente simplificada.Tenga en cuenta también que, dado que la excepción se vuelve a generar dentro de la
reraise()
función, aparecerá en cualquier rastreo que se genere, pero el resultado final es lo que desea.fuente
__str__
, puede obtener resultados no deseados. También tenga en cuenta que el segundo argumento se pasa al constructor dado por el primer argumento, lo que produce un poco sin sentidotype(e)(type(e)(e.message)
. En tercer lugar, e.message está en desuso a favor de e.args [0].En caso de que haya venido aquí buscando una solución para Python 3, el manual dice:
Ejemplo:
Que se ve así al final:
Convirtiendo un
TypeError
mensaje totalmente indescriptible en un bonito mensaje con sugerencias hacia una solución sin estropear la excepción originalfuente
e.args
, pero eso es una Tupla, por lo que no se puede cambiar. Así que primero copieargs
en una lista, luego modifíquelo, luego cópielo nuevamente como una Tupla:args = list(e.args)
args[0] = 'bar'
e.args = tuple(args)
Suponiendo que no desea o no puede modificar foo (), puede hacer esto:
De hecho, esta es la única solución aquí que resuelve el problema en Python 3 sin un mensaje feo y confuso "Durante el manejo de la excepción anterior, ocurrió otra excepción".
En caso de que la línea de resubir se agregue a la traza de la pila, escribir en
raise e
lugar deraise
hará el truco.fuente
e.args = ('mynewstr' + e.args[0],) + e.args[1:]
No me gustan todas las respuestas dadas hasta ahora. Todavía son demasiado detallados en mi humilde opinión. En salida de código y mensaje.
Todo lo que quiero tener es el seguimiento de la pila que apunta a la excepción de origen, sin cosas de excepción en el medio, por lo que no se crean nuevas excepciones, solo se vuelve a elevar el original con todos los estados relevantes del marco de la pila que condujeron allí.
Steve Howard dio una buena respuesta que quiero extender, no, reducir ... solo a Python 3.
Lo único nuevo es la expansión / desempaquetado de parámetros, que lo hace lo suficientemente pequeño y fácil de usar.
Intentalo:
Esto te dará:
Una simple impresión bonita podría ser algo así como
fuente
Un enfoque útil que utilicé es usar el atributo de clase como almacenamiento para detalles, ya que el atributo de clase es accesible tanto desde el objeto de clase como desde la instancia de clase:
Luego en tu código:
Y al detectar un error:
fuente
A diferencia de las respuestas anteriores, esto funciona frente a excepciones con muy mal
__str__
. Sin embargo, modifica el tipo, para factorizar__str__
implementaciones inútiles .Todavía me gustaría encontrar una mejora adicional que no modifique el tipo.
El rastreo original y el tipo (nombre) se conservan.
fuente
Proporcionaré un fragmento de código que utilizo a menudo cuando quiera agregar información adicional a una excepción. Trabajo tanto en Python 2.7 como en 3.6.
El código anterior da como resultado el siguiente resultado:
Sé que esto se desvía un poco del ejemplo proporcionado en la pregunta, pero sin embargo espero que alguien lo encuentre útil.
fuente
Puede definir su propia excepción que hereda de otro y crear su propio constructor para establecer el valor.
Por ejemplo:
fuente
message
excepción original (pero podría solucionarse, creo).Tal vez
fuente