Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Python logging has four core building blocks: loggers create and classify events, filters apply finer rules, handlers route records to destinations, and formatters decide how those records appear. A LogRecord carries the event information through the system.

What are the four parts of Python logging?

The Python Logging HOWTO describes the event information as passing among loggers, handlers, filters, and formatters in a LogRecord. A useful mental model is: logger creates and classifies; filter refines; handler routes; formatter presents. Each part has a distinct job, which makes it easier to understand why a message appears, disappears, or shows up more than once.

Logger: the interface your code calls

A logger is the object application code uses for calls such as debug(), info(), warning(), error(), and critical(). It creates a record for an event, applies the relevant level and logger filters, then passes accepted records toward handlers.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

In a Python module, a common pattern is logger = logging.getLogger(__name__). The resulting logger name follows the module’s package path, so a logger named myapp.storage sits beneath myapp in the logging hierarchy. This naming makes it possible to configure logging centrally while keeping log calls close to the code they describe. See the Python Logging HOWTO.

Filter: a custom decision point

Levels answer a severity question: should this event meet the configured threshold? A filter can express more specific rules, such as allowing only records associated with a particular subsystem or condition. Filters can be attached to loggers or handlers. Current API documentation also allows filters to modify a record or return a replacement record.

Placement matters. A filter attached to a logger is consulted for events logged on that logger; it is not automatically applied to records originating in every descendant logger. A handler filter sees records that reach that handler. This distinction is useful when deciding whether a rule should apply to one logger’s own events or to everything a particular output receives.

Handler: the route to an output

A handler sends records to a destination. The standard library includes handlers for streams such as the console, disk files, rotating files, sockets, and queues, among other destinations. A handler can also have its own severity level and filters. That makes it possible for two destinations to receive different subsets of the records.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Formatter: the final presentation

A formatter defines the layout of a record when a handler emits it. It can include fields such as severity, logger name, message, and time. The formatter does not select where the record goes; that is the handler’s job. For example, a console and a file can use different formatters even when both receive the same event.

How does a log record travel through the system?

Consider a call to logger.warning("Disk space is low") in a module whose logger was created with logging.getLogger(__name__). The documented flow works like this:

  1. The logger handles the call. The logger checks whether the call is enabled by its effective severity level and applies its own relevant filters. If the event is accepted, logging creates a LogRecord.
  2. The record reaches handlers. The logger offers the record to its handlers. If propagation is enabled, it can also pass the record up the logger hierarchy to ancestor handlers.
  3. Each handler makes its own checks. A handler’s level and filters determine whether that handler will emit the record. One handler may accept it while another rejects it.
  4. The handler formats and emits it. If accepted, the handler uses its formatter to produce the output and sends it to its destination, such as a stream or file.

This is a conceptual trace of the documented logging behavior, not a claim about a particular program’s runtime output. The outcome depends on the logger and handler levels, filters, attached handlers, and propagation settings. The HOWTO describes the logger hierarchy and record flow.

How do levels, filters, and propagation affect what appears?

The standard severity levels, in increasing order, are DEBUG, INFO, WARNING, ERROR, and CRITICAL. They describe operational meaning: detailed diagnostics, routine confirmation, an unexpected but continuing condition, a failed operation, or a severe condition. The default root logger level is WARNING, so informational and debug calls are not normally emitted unless configuration lowers the threshold.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A logger’s effective level may come from an ancestor when the logger itself has no explicitly assigned level. After the logger-level decision, a handler’s own level can still prevent it from emitting the record. Filters provide custom conditions in addition to those severity thresholds. These are separate decision points, not interchangeable settings.

Logger names form a dot-separated hierarchy. A child logger such as myapp.storage normally propagates records to handlers attached to its ancestors. This is why an application can often set up handlers centrally and use named loggers in individual modules.

Avoid duplicate output

A common configuration mistake is attaching an emitting handler to a child logger and another emitting handler to an ancestor. If the child’s record propagates upward, both handlers can emit it, so the message appears twice. Usually, attach a handler at the appropriate level in the hierarchy rather than at multiple points. Set propagation off for a logger only when it intentionally uses a separate route. The Python logging API reference explains this handler and propagation behavior.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How should you configure logging for your application?

For a small script or straightforward application, basicConfig() provides a quick way to configure the root logger, including a severity level, message format, and console or file destination. Larger applications may need named loggers and multiple handlers; Python documents explicit configuration, fileConfig(), and dictionary-based configuration with dictConfig(). The HOWTO recommends dictionary configuration for new applications and deployments, but that does not mean every project needs to replace a simpler setup.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When choosing an arrangement with multiple handlers, consider the destination, threshold, format, and propagation together. For example, the Logging Cookbook shows a configuration that sends all severities to a file while sending errors and more severe records to the console.

  • Destination: Decide which records belong on the console, in a file, in a queue, or elsewhere.
  • Severity threshold: Set what each destination should receive; a handler can have a different threshold from another handler.
  • Format: Include the information people need when reading that destination.
  • Propagation: Check whether records will also reach ancestor handlers and be emitted again.

For version-sensitive details, consult the documentation for the Python version your application uses. The references linked here cover Python 3.14.8, except the Cookbook example, which is from Python 3.10.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.