captura de mensajes de excepción de Python

522
import ftplib
import urllib2
import os
import logging
logger = logging.getLogger('ftpuploader')
hdlr = logging.FileHandler('ftplog.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)
FTPADDR = "some ftp address"

def upload_to_ftp(con, filepath):
    try:
        f = open(filepath,'rb')                # file to send
        con.storbinary('STOR '+ filepath, f)         # Send the file
        f.close()                                # Close file and FTP
        logger.info('File successfully uploaded to '+ FTPADDR)
    except, e:
        logger.error('Failed to upload to ftp: '+ str(e))

Esto no parece funcionar, me sale un error de sintaxis, ¿cuál es la forma correcta de hacerlo para registrar todo tipo de excepciones en un archivo?

Hellnar
fuente
2
Tu sangría está rota. Y omita el ,después except.
Sven Marnach
3
@SvenMarnach, si omite el ,after except, obtendrá global name 'e' is not defined, que no es mucho mejor que la sintaxis incorrecta.
Val
12
@Val: debería ser except Exception as eo except Exception, e, dependiendo de la versión de Python.
Sven Marnach
1
Probablemente esté en algún lugar alrededor de esas 8 respuestas, pero cuando abre un archivo, la parte cerrada nunca debe estar dentro de la declaración de prueba, sino en una declaración final o envuelta por una declaración con.
JC Rocamonde

Respuestas:

734

Debe definir qué tipo de excepción desea capturar. Por lo tanto, escriba en except Exception, e:lugar de except, e:una excepción general (que se registrará de todos modos).

Otra posibilidad es escribir todo el código try / except de esta manera:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception, e: # work on python 2.x
    logger.error('Failed to upload to ftp: '+ str(e))

en Python 3.xy las versiones modernas de Python 2.x usan en except Exception as elugar de except Exception, e:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception as e: # work on python 3.x
    logger.error('Failed to upload to ftp: '+ str(e))
eumiro
fuente
118
repr (e) le da la excepción (y la cadena del mensaje); str (e) solo da la cadena del mensaje.
barba blanca
11
Como alternativa para la excepción de registro, podría usar logger.exception(e)en su lugar. Registrará la excepción con rastreo en el mismo logging.ERRORnivel.
mbdevpl
1
@mbdevpl esto no parece ser cierto. Parece llamar a str () con la excepción: ideone.com/OaCOpO
KevinOrr
66
except Exception, e:me arroja un error de sintaxis en Python 3. ¿Se espera esto?
Charlie Parker el
27
@CharlieParker en Python3 writeexcept Exception as e:
eumiro
282

La sintaxis ya no es compatible con Python 3. Utilice lo siguiente en su lugar.

try:
    do_something()
except BaseException as e:
    logger.error('Failed to do something: ' + str(e))
sjtaheri
fuente
2
En realidad, debe usar logger.error ('Error al hacer algo:% s', str (e)) De esa manera, si su nivel de registrador está por encima del error, no hace la interpolación de cadenas.
avyfain
77
@avyfain: eres incorrecto. La declaración logging.error('foo %s', str(e))siempre se convertirá een una cadena. Para lograr lo que busca, usaría logging.error('foo %s', e), permitiendo así que el marco de registro realice (o no) la conversión.
Ron Dahlgren
1
Puede verificar en una REPL de python (aquí con Python 3.5.2 e ipython): vea mi esencia aquí
Ron Dahlgren
2
Como alternativa para la excepción de registro, podría usar logger.exception(e)en su lugar. Registrará la excepción con rastreo en el mismo logging.ERRORnivel.
mbdevpl
11
Cuidado con eso except BaseExceptiony except Exceptionno están en el mismo nivel. except Exceptionfunciona en Python3, pero no se capturará, KeyboardInterruptpor ejemplo (¡lo que puede ser muy conveniente si desea poder interrumpir su código!), mientras que BaseExceptiondetecta cualquier excepción. Vea este enlace para la jerarquía de excepciones.
jeannej
41

Actualizando esto a algo más simple para logger (funciona tanto para python 2 como para 3). No necesita el módulo de rastreo.

import logging

logger = logging.Logger('catch_all')

def catchEverythingInLog():
    try:
        ... do something ...
    except Exception as e:
        logger.error(e, exc_info=True)
        ... exception handling ...

Esta es ahora la forma antigua (aunque todavía funciona):

import sys, traceback

def catchEverything():
    try:
        ... some operation(s) ...
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        ... exception handling ...

exc_value es el mensaje de error.

berniey
fuente
2
Este sería mi método preferido. Simplemente imprimir la cadena es útil para iniciar sesión, supongo, pero si necesito hacer algo con esa información, necesito más que solo una cadena.
sulimmesh
3
No necesita 'importar rastreo' en el segundo ejemplo, ¿verdad?
starikoff
34

Hay algunos casos en los que puede usar el mensaje electrónico o los mensajes electrónicos . Pero no funciona en todos los casos. De todos modos, lo más seguro es usar el str (e)

try:
  ...
except Exception as e:
  print(e.message)
Slipstream
fuente
42
El problema con esto es, por ejemplo, si usted except Exception as e, y ees una IOError, se obtiene e.errno, e.filenamey e.strerror, aunque aparentemente no hay e.message(al menos en Python 2.7.12). Si desea capturar el mensaje de error, use str(e), como en las otras respuestas.
epalm
@epalm ¿Qué pasa si detecta el IOError antes de la excepción?
Albert Thompson
@ HeribertoJuárez ¿Por qué atrapar casos especiales mientras que simplemente puede convertirlo en una cuerda?
HosseyNJF
25

Si desea la clase de error, el mensaje de error y el seguimiento de la pila (o algunos de esos), use sys.exec_info().

Código de trabajo mínimo con algún formato:

import sys
import traceback

try:
    ans = 1/0
except BaseException as ex:
    # Get current system exception
    ex_type, ex_value, ex_traceback = sys.exc_info()

    # Extract unformatter stack traces as tuples
    trace_back = traceback.extract_tb(ex_traceback)

    # Format stacktrace
    stack_trace = list()

    for trace in trace_back:
        stack_trace.append("File : %s , Line : %d, Func.Name : %s, Message : %s" % (trace[0], trace[1], trace[2], trace[3]))

    print("Exception type : %s " % ex_type.__name__)
    print("Exception message : %s" %ex_value)
    print("Stack trace : %s" %stack_trace)

Lo que da el siguiente resultado:

Exception type : ZeroDivisionError
Exception message : division by zero
Stack trace : ['File : .\\test.py , Line : 5, Func.Name : <module>, Message : ans = 1/0']

La función sys.exc_info () le brinda detalles sobre la excepción más reciente. Devuelve una tupla de (type, value, traceback).

tracebackes una instancia de objeto de rastreo. Puede formatear la traza con los métodos proporcionados. Se puede encontrar más en la documentación de rastreo .

Kavindu Dodanduwa
fuente
3
El uso también e.__class__.__name__ puede devolver la clase de excepción.
kenorb
19

Puede usar logger.exception("msg")para registrar excepciones con rastreo:

try:
    #your code
except Exception as e:
    logger.exception('Failed: ' + str(e))
Peter
fuente
Coincidentemente, e.msges la representación en cadena de la Exceptionclase.
MarkHu
55
O simplemente logger.exception(e).
mbdevpl
5

Puede intentar especificar el tipo BaseException explícitamente. Sin embargo, esto solo capturará derivados de BaseException. Si bien esto incluye todas las excepciones proporcionadas por la implementación, también es posible generar clases arbitrarias de estilo antiguo.

try:
  do_something()
except BaseException, e:
  logger.error('Failed to do something: ' + str(e))
Heini Høgnason
fuente
4

Use str (ex) para imprimir la ejecución

try:
   #your code
except ex:
   print(str(ex))
Niraj Trivedi
fuente
2

Para los futuros luchadores, en Python 3.8.2 (y quizás algunas versiones anteriores), la sintaxis es

except Attribute as e:
    print(e)
syter
fuente
1

Usando str(e)o repr(e)para representar la excepción, no obtendrá el seguimiento real de la pila, por lo que no es útil encontrar dónde está la excepción.

Después de leer otras respuestas y el documento del paquete de registro, las siguientes dos formas funcionan muy bien para imprimir el seguimiento real de la pila para una depuración más fácil:

usar logger.debug()con parámetroexc_info

try:
    # my code
exception SomeError as e:
    logger.debug(e, exc_info=True)

utilizar logger.exception()

o podemos usar directamente logger.exception()para imprimir la excepción.

try:
    # my code
exception SomeError as e:
    logger.exception(e)
jdhao
fuente