Python exception logging: keep the traceback and enough request context
Use a named logger, configure the application once, and attach safe context without duplicating every error.
On this page
The short answer
Inside an exception handler, logger.exception records an ERROR event with the current exception information. Configure handlers in the application entry point and use getLogger(__name__) in individual modules. Include a safe operation or request identifier so the traceback can be related to the failing action. Logging records the failure; the program must separately decide whether to recover, return an error or re-raise.
Choose the event you need to record
An exception object and an operational event answer different questions. The exception describes what failed; the event can identify which action was in progress. Before adding logging, decide who will read the record and what they need to investigate. A short message naming the operation and a nonsecret correlation identifier is usually more useful than repeating an entire request body or dumping every local variable.
Configure logging at the application boundary
For a standalone script, configure logging before the application begins doing work. The example below uses basicConfig once and obtains a named logger. A larger application may use a different configuration mechanism, but ownership should still be clear. A reusable library should expose named loggers and let its caller choose handlers, destinations and levels rather than unconditionally replacing application configuration.
Use exception information inside the handler
logger.exception is intended for an exception handler, where the current exception information is available. Calling logger.error with only the exception text omits the traceback unless exception information is explicitly requested. Conversely, writing a traceback does not require treating every recoverable condition as a fatal application failure. Choose the event level and recovery policy according to the operation, not solely according to the exception class name.
Read a complete small example
This constructed standalone script deliberately passes a nonnumeric string to int. The expected log contains an ERROR message with request_id=demo1 and exception information ending in ValueError. Exact traceback paths and line numbers depend on where the script is saved, so no fixed full traceback is promised. The example demonstrates a logging call; its caught exception is not automatically propagated to the caller.
import logging
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s %(message)s")
logger = logging.getLogger(__name__)
request_id = "demo1"
try:
int("bad")
except ValueError:
logger.exception("Could not parse quantity; request_id=%s", request_id)
Decide who owns the final error record
If a lower layer logs an exception and re-raises it, and an upper layer also logs it, one failure may appear twice. Decide which layer has enough context to create the operational record. A lower layer can add information by raising an appropriate exception, while the boundary logs the final failure. This is a design choice rather than a requirement that every exception must be logged exactly once everywhere.
Diagnose repeated output through handlers
Duplicate-looking records can also result from attaching a handler to a child logger while allowing propagation to an ancestor that has another handler. Inspect the logger hierarchy and handler configuration before removing application events. Logger and handler levels can both affect whether output appears. Suppressing propagation without understanding the destinations may hide records from a central sink as well as removing a duplicate console line.
Keep sensitive context out of the record
Use an opaque request identifier or a carefully selected operation name. Do not include passwords, authorization headers, API keys or an entire unfiltered request payload. Exception messages themselves can contain user input or connection details, so a safe logging call is not proof that every resulting traceback is safe to retain. Apply access, retention and redaction policies appropriate to the actual application and log destination.
Separate diagnostics from program behavior
A logging call neither retries the operation nor selects the response returned to a client. After recording the event, deliberately choose whether to continue with a valid fallback, return a documented failure, or re-raise. Document the choice near the error boundary. If the program continues, avoid making later code depend on a value that was never successfully created by the failing statement.
Things to check
- Configure handlers in the application, not every module.
- Use exception information while handling the exception.
- Include a safe correlation identifier.
- Inspect handlers and propagation when output repeats.
- Define recovery or propagation separately from logging.
Where this applies
The script illustrates standard-library logging and a caught ValueError. It is not a complete production logging configuration and does not demonstrate a deployed log sink, automatic redaction, retries or an executed application test.