DEV Community

Sachin G L
Sachin G L

Posted on

Python Logging Patterns for Production Scripts

Introduction

Logging is an essential part of any production software. It helps in debugging, monitoring, and maintaining the software. Python’s built-in logging module provides a flexible and powerful logging framework. This article explains common Python logging patterns and best practices for production scripts.

Log Levels

Python's logging module defines log levels which determine the severity of the message. Common log levels include DEBUG, INFO, WARNING, ERROR, and CRITICAL. Each log level corresponds to a numeric value, with DEBUG being the lowest and CRITICAL being the highest.

import logging
logging.basicConfig(level=logging.INFO)
Enter fullscreen mode Exit fullscreen mode

In this example, we set the log level to INFO, meaning only messages at or above INFO level will be captured.

Handlers and Formatters

Handlers control where and how logs are written. Common handlers include StreamHandler for console output, FileHandler for file output, and SMTPHandler for sending emails. Each handler can have its own formatter, which specifies the format of the log message. Here’s an example of a custom handler with a formatter:

from logging import Handler, Formatter

class CustomHandler(Handler):
    def __init__(self, level=logging.INFO):
        super().__init__(level)

    def emit(self, record):
        # Implement custom emit logic
        pass

    def format(self, record):
        return f'{record.levelname}: {record.getMessage()}'
Enter fullscreen mode Exit fullscreen mode

Common Logging Patterns

  1. Structured Logging: Use structured data like dictionaries to provide context and meaning to log messages. This pattern is especially useful for traceability and querying.
import logging

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

data = {'user_id': 123, 'action': 'view', 'timestamp': '2023-01-01 12:00:00'}
logger.info('User viewed page', extra=data)
Enter fullscreen mode Exit fullscreen mode
  1. Rotating File Handlers: Use RotatingFileHandler to limit log file size or number of files. This ensures logs don’t consume excessive disk space.
import logging
from logging.handlers import RotatingFileHandler

handler = RotatingFileHandler('app.log', maxBytes=1000000, backupCount=5)
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logging.getLogger(__name__).addHandler(handler)
Enter fullscreen mode Exit fullscreen mode
  1. Logging Exceptions: Use the logging.exception() method to log exceptions without causing the program to crash. This helps in tracking down issues.
import logging

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

try:
    # Code that may raise an exception
    1 / 0
except Exception as e:
    logger.exception('An error occurred')
Enter fullscreen mode Exit fullscreen mode

Common Pitfalls

  1. Ignoring Logs: Don’t ignore logs by not configuring handlers. Logs are a crucial part of the debugging process and must be written somewhere.

  2. Over-Logging: Avoid over-logging by using appropriate log levels and avoiding unnecessary logging. Log only what is needed for debugging and monitoring.

  3. Incorrect Handlers: Ensure handlers are correctly set up and configured. Mixing up handlers or not setting up a handler at all can lead to logs being ignored or incorrectly formatted.

Conclusion

Python’s logging module offers a robust framework for logging. By understanding and utilizing log levels, handlers, and formatters, developers can create a reliable logging system that aids in debugging, monitoring, and maintenance. Structured logging and rotating handlers are particularly useful for traceability and resource management. Avoiding common pitfalls such as ignoring logs and over-logging will lead to more efficient and effective logging practices.

Top comments (0)