Python - Logging

Overview

Estimated time: 25–35 minutes

The logging module provides a flexible framework for application logs. Learn practical configuration, handlers/formatters, and patterns that scale from scripts to services.

Learning Objectives

  • Use logger hierarchies and levels effectively.
  • Configure handlers and formatters (console/file) without global side-effects.
  • Adopt best practices for parameterized logging and structured output.

Prerequisites

  • Exceptions and basic modules

Examples

import logging

logger = logging.getLogger("app")
logger.setLevel(logging.INFO)

handler = logging.StreamHandler()
fmt = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
handler.setFormatter(fmt)
logger.addHandler(handler)

logger.info("starting app version=%s", "1.0")
try:
    1/0
except ZeroDivisionError:
    logger.exception("division failed")

Expected Output: time-stamped lines including level, logger name, and message; stacktrace logged by exception().

Common Pitfalls

  • Using f-strings for logging: prefers parameterized logging (logger.info("x=%s", x)) to avoid formatting when disabled.
  • Configuring root logger implicitly from a library; instead, configure in the application entry point.
  • Duplicate logs from multiple handlers; watch for propagation (logger.propagate = False when appropriate).

Best Practices

  • Centralize configuration (e.g., in main) and expose loggers via logging.getLogger(__name__) in modules.
  • Prefer structured logging (JSON) for services; include request IDs, user IDs, etc.
  • Use appropriate levels: DEBUG/INFO/WARNING/ERROR/CRITICAL; keep logs actionable.

Checks for Understanding

  1. Why is parameterized logging preferred to f-strings?
  2. How do you prevent a child logger’s messages from being duplicated?
Show answers
  1. It defers formatting unless the message will be emitted and is often faster and safer.
  2. Set logger.propagate = False or adjust handlers/levels so they aren’t attached multiple times.

Exercises

  1. Configure rotating file logs using RotatingFileHandler with a max size and backups.
  2. Emit JSON-structured logs (use json.dumps in a custom Formatter or a library).