21  Logging (Advanced)

21.1 Logging to Multiple Destination

To verbosely log everything into a log file, while duplicating only the more interesting messages onto the console:

import logging

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
fmt = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")

# Warnings and higher only on the console.
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.WARNING)
logger.addHandler(console_handler)
console_handler.setFormatter(fmt)


# But allow everything to go into the log file.
logfile_handler = logging.FileHandler("mylog.log")
logger.addHandler(logfile_handler)
logfile_handler.setFormatter(fmt)

logger.warning("This goes to both the console, AND into log.txt.")
logger.debug("While this only goes to the file.")
2025-05-11 22:28:02,049 - WARNING - This goes to both the console, AND into log.txt.

21.2 Logging in Package

For example, in __init__.py or a new logging.py file for package radreportparser

import logging
import sys

def _setup_default_logger():
    """Set up the default logger for radreportparser.
    
    This creates a default configuration that:
    1. Shows warnings and above to stderr
    2. Uses a simple format that's easy to read
    3. Only configures logging for this package, not the root logger
    
    Users can still override this configuration by:
    1. Getting the logger with logging.getLogger('radreportparser')
    2. Removing the default handler with logger.removeHandler()
    3. Adding their own handlers and configuration
    """
    logger = logging.getLogger("radreportparser")
    
    # Only add handler if none exist (avoid duplicate handlers)
    if not logger.handlers:
        # Create default handler
        handler = logging.StreamHandler(sys.stderr)
        handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s [%(name)s] - %(message)s'))
        
        # Add handler and set level
        logger.addHandler(handler)
        logger.setLevel(logging.WARNING)
    
    return logger

# Create and configure the default logger
logger = _setup_default_logger()

Use by logger.warning() etc.