¿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 messagecampo 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 unmessageatributo o no sea separado..messagepor error es una forma estándar o no?print(msg)es solo un atajo paraprint(str(msg))messageestá en desuso.Respuestas:
Si observa la documentación de los errores incorporados , verá que la mayoría de las
Exceptionclases asignan su primer argumento comomessageatributo. Sin embargo, no todos lo hacen.En particular,
EnvironmentError(con subclasesIOErroryOSError) tiene un primer argumento deerrno, segundo destrerror. No haymessage...strerrores aproximadamente análogo a lo que normalmente sería unmessage.De manera más general, las subclases de
Exceptionpueden hacer lo que quieran. Pueden tener o no unmessageatributo. Es posible que los mensajes de correo electrónico integrados futurosExceptionno tengan unmessageatributo. Es posible que cualquierExceptionsubclase importada de bibliotecas de terceros o código de usuario no tenga unmessageatributo.Creo que la forma correcta de manejar esto es identificar las
Exceptionsubclases 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
printalgo, creo queExceptiones más probable que la impresión de la captura en sí haga lo que desee, tengamessageo 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
messageatributo e imprimirlo o imprimir elExceptionobjeto como respaldo.try: pass except Exception as e: print getattr(e, 'message', repr(e))La llamada a
repres 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
reprpodrí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
getattrlanza 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).strlugar derepr.str,reprsolo 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.messagecedió solo0o 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 logPython 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 depipo 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
argsatributo, 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 handlingfuente