values setlevel loggeradapter logger log info example python logging exception-handling

setlevel - Registrando excepciones no detectadas en Python



python logging example to file (8)

Aquí hay un pequeño ejemplo completo que también incluye algunos otros trucos:

import sys import logging logger = logging.getLogger(__name__) handler = logging.StreamHandler(stream=sys.stdout) logger.addHandler(handler) def handle_exception(exc_type, exc_value, exc_traceback): if issubclass(exc_type, KeyboardInterrupt): sys.__excepthook__(exc_type, exc_value, exc_traceback) return logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) sys.excepthook = handle_exception if __name__ == "__main__": raise RuntimeError("Test unhandled")

  • Ignore KeyboardInterrupt para que un programa de consola python pueda salir con Ctrl + C.

  • Confíe totalmente en el módulo de registro de Python para formatear la excepción.

  • Use un registrador personalizado con un controlador de ejemplo. Éste cambia la excepción no controlada para ir a stdout en lugar de a stderr, pero puede agregar todo tipo de manejadores en este mismo estilo al objeto logger.

¿Cómo se causan excepciones no detectadas a la salida a través del módulo de logging lugar de stderr ?

Me doy cuenta de que la mejor manera de hacerlo sería:

try: raise Exception, ''Throwing a boring exception'' except Exception, e: logging.exception(e)

Pero mi situación es tal que sería realmente agradable si logging.exception(...) se invoca automáticamente cada vez que una excepción no se logging.exception(...) .


Aunque la respuesta de @gnu_lorien me dio un buen punto de partida, mi programa falla en la primera excepción.

Vine con una solución personalizada (y / o) mejorada, que registra silenciosamente Excepciones de funciones que están decoradas con @handle_error .

import logging __author__ = ''ahmed'' logging.basicConfig(filename=''error.log'', level=logging.DEBUG) def handle_exception(exc_type, exc_value, exc_traceback): import sys if issubclass(exc_type, KeyboardInterrupt): sys.__excepthook__(exc_type, exc_value, exc_traceback) return logging.critical(exc_value.message, exc_info=(exc_type, exc_value, exc_traceback)) def handle_error(func): import sys def __inner(*args, **kwargs): try: return func(*args, **kwargs) except Exception, e: exc_type, exc_value, exc_tb = sys.exc_info() handle_exception(exc_type, exc_value, exc_tb) finally: print(e.message) return __inner @handle_error def main(): raise RuntimeError("RuntimeError") if __name__ == "__main__": for _ in xrange(1, 20): main()


Como señaló Ned, sys.excepthook se invoca cada vez que se sys.excepthook una excepción y no se detecta. La consecuencia práctica de esto es que en su código puede anular el comportamiento predeterminado de sys.excepthook para hacer lo que desee (incluido el uso de logging.exception ).

Como ejemplo de hombre de paja:

>>> import sys >>> def foo(exctype, value, tb): ... print ''My Error Information'' ... print ''Type:'', exctype ... print ''Value:'', value ... print ''Traceback:'', tb ...

Anular sys.excepthook :

>>> sys.excepthook = foo

Confirme el error de sintaxis obvio (omita los dos puntos) y obtenga información de error personalizada:

>>> def bar(a, b) My Error Information Type: <type ''exceptions.SyntaxError''> Value: invalid syntax (<stdin>, line 1) Traceback: None

Para obtener más información acerca de sys.excepthook : http://docs.python.org/library/sys.html#sys.excepthook


El método sys.excepthook se invocará si no se sys.excepthook una excepción: http://docs.python.org/library/sys.html#sys.excepthook

Cuando se genera una excepción y no se detecta, el intérprete llama a sys.excepthook con tres argumentos, la clase de excepción, la instancia de excepción y un objeto de rastreo. En una sesión interactiva, esto sucede justo antes de que se devuelva el control al aviso; en un programa de Python esto sucede justo antes de que el programa salga. El manejo de tales excepciones de nivel superior se puede personalizar asignando otra función de tres argumentos a sys.excepthook.


Envuelva la llamada de entrada de la aplicación en un try...except bloque para que pueda capturar y registrar (y quizás volver a subir) todas las excepciones no detectadas. Por ejemplo, en lugar de:

if __name__ == ''__main__'': main()

Hacer esto:

if __name__ == ''__main__'': try: main() except Exception as e: logger.exception(e) raise


Para construir sobre la respuesta de Jacinda, pero usando un objeto logger:

def catchException(logger, typ, value, traceback): logger.critical("My Error Information") logger.critical("Type: %s" % typ) logger.critical("Value: %s" % value) logger.critical("Traceback: %s" % traceback) # Use a partially applied function func = lambda typ, value, traceback: catchException(logger, typ, value, traceback) sys.excepthook = func


Por qué no:

import sys import logging import traceback def log_except_hook(*exc_info): text = "".join(traceback.format_exception(*exc_info)) logging.error("Unhandled exception: %s", text) sys.excepthook = log_except_hook None()

Aquí está la salida con sys.excepthook como se ve arriba:

$ python tb.py ERROR:root:Unhandled exception: Traceback (most recent call last): File "tb.py", line 11, in <module> None() TypeError: ''NoneType'' object is not callable

Aquí está la salida con el sys.excepthook comentado:

$ python tb.py Traceback (most recent call last): File "tb.py", line 11, in <module> None() TypeError: ''NoneType'' object is not callable

La única diferencia es que el primero tiene ERROR:root:Unhandled exception: al comienzo de la primera línea.


Tal vez podrías hacer algo en la parte superior de un módulo que redireccione stderr a un archivo, y luego registrar ese archivo en la parte inferior

sock = open(''error.log'', ''w'') sys.stderr = sock doSomething() #makes errors and they will log to error.log logging.exception(open(''error.log'', ''r'').read() )