Learn logging

The standard library's flexible logging framework for apps and libraries

13 lessons · 2 hours · 4 levels · covers logging Python 3.13

logging is Python's built-in system for recording what a program does, with levels, named loggers, pluggable handlers and formatters. Every serious application and library uses it, and frameworks such as Django, FastAPI and Celery plug into it. Learning it well means readable diagnostics in development and searchable, structured logs in production.

Before you start

logging builds on these; the tree links to the exact lessons you need.

How deep do you want to go?

1. EssentialsRead and write simple code, do the everyday basics4 lessons · 33 min in total
2. PracticalUse it productively at work, with the usual idioms7 lessons · 1 hour in total
3. AdvancedThe less common features, performance and trade-offs10 lessons · 2 hours in total
4. ExpertInternals and the edge cases experts know13 lessons · 2 hours in total

The logging tree

loggingYour first log messagesYour first logmessagesNamed loggers: getLogger(__name__)Named loggers:getLogger(__name__)Choosing and filtering levelsChoosing andfiltering levelsMessage arguments and formatsMessage argumentsand formatsHandlers and formattersHandlers andformattersPropagation and the logger treePropagation and thelogger treeLogging exceptionsLogging exceptionsModules and importsModules and importsExceptions in depthExceptions in depthDictionariesDictionariesThreads, processes and concurrent.futuresThreads, processesand concurrent.fut…
Essentials and Practical shown (7 of 13 lessons); the full list is below. Click a lesson to read it.

All 13 lessons, in order

Logging basics

  1. Your first log messages · Essentials · 8 min

    Replace print debugging with logging.basicConfig and the five standard level functions.

  2. Named loggers: getLogger(__name__) · Essentials · 8 min

    Create one logger per module with logging.getLogger(__name__) instead of logging through the root logger.

  3. Choosing and filtering levels · Essentials · 8 min

    Pick the right level for each message and understand how logger levels filter them.

  4. Message arguments and formats · Essentials · 9 min

    Pass values as arguments for lazy %-formatting, and control each line's layout with format attributes.

Handlers and the logger tree

  1. Handlers and formatters · Practical · 12 min

    Send records to several destinations, each with its own level and format, using handlers and formatters.

  2. Propagation and the logger tree · Practical · 11 min

    Follow how records bubble up the dotted logger hierarchy to ancestor handlers, and fix duplicate log lines.

  3. Logging exceptions · Practical · 9 min

    Record full tracebacks with logger.exception() or exc_info=True, and add stack context with stack_info.

Configuration and context

  1. Configuring with dictConfig · Advanced · 14 min

    Describe loggers, handlers and formatters declaratively with logging.config.dictConfig.

  2. Adding context: extra, adapters, filters · Advanced · 13 min

    Attach request IDs and other context to records with extra=, LoggerAdapter, or a filter reading contextvars.

  3. Logging in libraries · Advanced · 9 min

    Log from reusable packages correctly: named loggers, a NullHandler, and no configuration.

Production logging

  1. Non-blocking logging with queues · Expert · 13 min

    Move slow handler I/O off your threads with QueueHandler and QueueListener.

  2. Structured JSON logs · Expert · 12 min

    Emit one JSON object per line with a custom Formatter so log platforms can index every field.

  3. How a log call works inside · Expert · 12 min

    Trace a record from logger call through filters, handlers and locks, and know the performance costs.