Log an exception with its traceback in Python

Use logger.exception or exc_info to preserve exception tracebacks, and configure a hook for uncaught main-thread exceptions.

Best practices
Log an exception with its traceback in Python illustration

Inside an except block, call logger.exception('message') to log the active exception and its traceback at ERROR level. logger.error('message', exc_info=True) provides the same exception information.

Log the exception you caught

import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

try:
    int('not a number')
except ValueError:
    logger.exception('Could not parse the input')

The output identifies the exception type and message, together with the frames and line numbers leading to the failure. Decide separately whether to recover or re-raise: logging does not change exception handling semantics.

Supply the exception explicitly

try:
    int('invalid')
except ValueError as error:
    logger.error('Parsing failed', exc_info=error)

Passing an exception instance has been supported since Python 3.5. You can also pass (exception_type, exception_value, traceback). An explicitly retained exception can be logged outside its original handler, but keeping it also keeps its traceback and potentially referenced objects alive until released.

Handle uncaught main-thread exceptions

import sys

def handle_uncaught(exc_type, exc_value, exc_tb):
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_tb)
        return
    logger.critical(
        'Uncaught exception',
        exc_info=(exc_type, exc_value, exc_tb),
    )

sys.excepthook = handle_uncaught

Install this once during application startup. It does not cover every background execution mechanism: thread exceptions have threading.excepthook, while asynchronous tasks may need event-loop error handling. Frameworks can also install their own hooks.

FAQ

What level does exception() use?

ERROR. Use another logging method with exc_info when you need a different level.

Does exc_info=True work when there is no active exception?

It has no exception to retrieve and can print NoneType: None. Pass an explicit exception or tuple if you retained one. To see the current call stack without an exception, use stack_info=True; that is different from the traceback of a failure.

See Python logging reference.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting