Understanding Log Levels

The logging module defines several log levels that indicate the severity of events. These levels, in increasing order of severity, are:

Log LevelNumeric ValueDescription
DEBUG10Detailed information, typically of interest only when diagnosing problems.
INFO20Confirmation that things are working as expected.
WARNING30An indication that something unexpected happened, or indicative of some problem in the near future.
ERROR40Due to a more serious problem, the software has not been able to perform some function.
CRITICAL50A very serious error, indicating that the program itself may be unable to continue running.

Basic Configuration

To get started with logging, you need to configure the logging system. This can be done using basicConfig() method. Here’s a simple example:

import logging

# Basic configuration
logging.basicConfig(level=logging.INFO, 
                    format='%(asctime)s - %(levelname)s - %(message)s')

# Example usage
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

In this example, only messages with a severity level of INFO and above will be displayed because we set the logging level to INFO.

Advanced Configuration

For more complex applications, you may want to configure logging using a configuration file or a dictionary. Here’s an example of using a dictionary to configure logging:

import logging
import logging.config

# Define logging configuration
logging_config = {
    'version': 1,
    'formatters': {
        'simple': {
            'format': '%(asctime)s - %(levelname)s - %(message)s'
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'simple',
            'level': 'DEBUG'
        },
        'file': {
            'class': 'logging.FileHandler',
            'filename': 'app.log',
            'formatter': 'simple',
            'level': 'ERROR'
        },
    },
    'loggers': {
        'my_logger': {
            'handlers': ['console', 'file'],
            'level': 'DEBUG',
            'propagate': False
        },
    }
}

# Apply configuration
logging.config.dictConfig(logging_config)

# Create a logger
logger = logging.getLogger('my_logger')

# Example usage
logger.debug('Debug message')
logger.info('Info message')
logger.warning('Warning message')
logger.error('Error message')
logger.critical('Critical message')

In this example, we have configured two handlers: one for console output and another for logging errors to a file named app.log.

Logging Exceptions

Logging exceptions is crucial for debugging. You can log exceptions using the exception() method, which should be called within an exception handler. Here’s an example:

try:
    1 / 0
except ZeroDivisionError:
    logger.exception("An exception occurred")

This will log the stack trace along with the message, helping you understand what went wrong.

Performance Considerations

Logging can introduce performance overhead, especially if you log a lot of messages. Here are some best practices to mitigate performance issues:

  1. Use Appropriate Log Levels: Avoid logging at the DEBUG level in production environments unless necessary.
  2. Lazy Evaluation: Use lazy evaluation for log messages that are expensive to compute:
   logger.debug("The result is: %s", expensive_computation())

This way, expensive_computation() is only called if the log level is set to DEBUG.

  1. Batch Logging: If possible, batch log messages to reduce the number of I/O operations.

Formatting Log Messages

Customizing the format of log messages can enhance readability. The format can include timestamps, log levels, and other contextual information. Here’s an example of a more detailed log format:

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

Conclusion

Effective logging is a critical component of robust software development. By leveraging Python's logging module, you can gain insights into your application's behavior, troubleshoot issues, and maintain a clear record of events. Remember to configure your logging appropriately, choose the right log levels, and format your messages for clarity.

Learn more with useful resources: