¿Cuál es la mejor manera de obtener mensajes de excepciones de los componentes de la biblioteca estándar en Python?
Noté que en algunos casos puedes obtenerlo a través de un message
campo como este:
try:
pass
except Exception as ex:
print(ex.message)
pero en algunos casos (por ejemplo, en caso de errores de socket) tienes que hacer algo como esto:
try:
pass
except socket.error as ex:
print(ex)
Me preguntaba si existe alguna forma estándar de cubrir la mayoría de estas situaciones.
python
exception
exception-handling
Corazón congelado
fuente
fuente
except Foo as bar:
es lo mismo queexcept Foo, bar:
(excepto que el primero es más nuevo y continuará funcionando en 3.x), ya sea que el error venga con unmessage
atributo o no sea separado..message
por error es una forma estándar o no?print(msg)
es solo un atajo paraprint(str(msg))
message
está en desuso.Respuestas:
Si observa la documentación de los errores incorporados , verá que la mayoría de las
Exception
clases asignan su primer argumento comomessage
atributo. Sin embargo, no todos lo hacen.En particular,
EnvironmentError
(con subclasesIOError
yOSError
) tiene un primer argumento deerrno
, segundo destrerror
. No haymessage
...strerror
es aproximadamente análogo a lo que normalmente sería unmessage
.De manera más general, las subclases de
Exception
pueden hacer lo que quieran. Pueden tener o no unmessage
atributo. Es posible que los mensajes de correo electrónico integrados futurosException
no tengan unmessage
atributo. Es posible que cualquierException
subclase importada de bibliotecas de terceros o código de usuario no tenga unmessage
atributo.Creo que la forma correcta de manejar esto es identificar las
Exception
subclases específicas que desea capturar, y luego capturar solo aquellas en lugar de todo con unexcept Exception
, luego utilizar los atributos que esa subclase específica defina como desee.Si debe
print
algo, creo queException
es más probable que la impresión de la captura en sí haga lo que desee, tengamessage
o no un atributo.También puede verificar el atributo de mensaje si lo desea, así, pero realmente no lo sugeriría ya que parece desordenado:
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)
fuente
str(ex)
lugar de soloex
?print()
llama automáticamentestr()
. No hay razón para llamarlo manualmente usted mismo, aunque es inofensivo ya que llamarstr()
a una cadena simplemente devolverá la cadena en sí.str()
si el mensaje es de tipounicode
.Para mejorar la respuesta proporcionada por @artofwarfare , aquí está lo que considero una forma más ordenada de verificar el
message
atributo e imprimirlo o imprimir elException
objeto como respaldo.try: pass except Exception as e: print getattr(e, 'message', repr(e))
La llamada a
repr
es opcional, pero la encuentro necesaria en algunos casos de uso.Actualización n. ° 1:
Siguiendo el comentario de @MadPhysicist , aquí hay una prueba de por qué la llamada a
repr
podría ser necesaria. Intente ejecutar el siguiente código en su intérprete:try: raise Exception except Exception as e: print(getattr(e, 'message', repr(e))) print(getattr(e, 'message', str(e)))
Actualización n. ° 2:
Aquí hay una demostración con detalles para Python 2.7 y 3.5: https://gist.github.com/takwas/3b7a6edddef783f2abddffda1439f533
fuente
getattr
lanza una excepción si el objeto pasado no tiene el atributo solicitado. Si quería hacer algo así, creo que se debe utilizar el tercer argumento opcional paragetattr
, de esta manera:print getattr(e, 'message', e)
. Probablemente mejor que lo que hice. Otra opción seríaprint(e.message if hasattr(e, 'message') else e)
.str
lugar derepr
.str
,repr
solo agrega el nombre de la clase. En lugar de usarrepr
, propongo usarprint('{e.__class__.__name__}: {e}'.format(e=e))
. La salida de impresión es más limpia y se adhiere a la salida del propio aumento.'{e.__class__.__module__}.{e.__class__.__name__}: {e}'
repr(e)
fue por ahora la única solución que me ayudó a imprimir al menos una cantidad mínima de información sobre un error que detecto en alguna circunstancia particular.repr(e)
produceKeyError(0,)
(que es el error), mientras questr(e)
oe.message
cedió solo0
o nada respectivamente.Yo tuve el mismo problema. Creo que la mejor solución es usar log.exception, que imprimirá automáticamente el seguimiento de la pila y el mensaje de error, como:
try: pass log.info('Success') except: log.exception('Failed')
fuente
log
? Acabo de probarimport log
Python 2.7.13 y recibí un mensaje de que no hay ningún módulo con ese nombre. ¿Es algo que agregó a través depip
o se agregó en una versión más nueva de python (lo sé, lo sé, necesito actualizar a Python 3 ... Lo haré tan pronto como CentOS deje de enviarse con Python 2 de forma predeterminada ...)import logging
\ nlog = logging.getLogger(__name__)
Yo también tuve el mismo problema. Profundizando en esto, encontré que la clase Exception tiene un
args
atributo, que captura los argumentos que se usaron para crear la excepción. Si reduce las excepciones que excepto se detectarán a un subconjunto, debería poder determinar cómo se construyeron y, por lo tanto, qué argumento contiene el mensaje.try: # do something that may raise an AuthException except AuthException as ex: if ex.args[0] == "Authentication Timeout.": # handle timeout else: # generic handling
fuente