Python Logging Module: In-Depth Usage Guide
The Python logging module is a powerful tool for tracking events that happen when software runs. This guide covers configuration from basic to advanced levels, including dictionary-based configuration.
Simple Function Configuration
By default, Python's logging module prints logs to standard output, showing only messages with a level of WARNING or higher. The default level order is: CRITICAL > ERROR > WARNING > INFO > DEBUG. The default format is: level:logger_name:user_message.
import logging
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
Log Format and Level Parameters
Log Levels and Their Numeric Values
DEBUG: 10INFO: 20WARNING: 30ERROR: 40CRITICAL: 50
Format String Placeholders
| Placeholder | Description |
|---|---|
%(name)s |
Logger name |
%(levelno)s |
Numeric log level |
%(levelname)s |
Text log level |
%(pathname)s |
Full pathname of the source file (if available) |
%(filename)s |
Filename of the source file |
%(module)s |
Module name |
%(funcName)s |
Function name |
%(lineno)d |
Line number in the source file |
%(created)f |
Time when the log record was created (Unix timestamp) |
%(relativeCreated)d |
Milliseconds since Logger creation |
%(asctime)s |
Human-readable time (e.g., 2003-07-08 16:49:45,896) |
%(thread)d |
Thread ID (if available) |
%(threadName)s |
Thread name (if available) |
%(process)d |
Process ID (if available) |
%(message)s |
The logged message |
basicConfig() Parameters
filename: Specify a file to write logs to.filemode: File open mode (default'a', can be'w'). Used only whenfilenameis set.format: Log format string.datefmt: Date/time format string.level: Root logger level.stream: Stream to use (e.g.,sys.stderr,sys.stdout). Ignored iffilenameis also specified.handlers: List of handlers to add. Overridesfilename/stream.
Basic Logging Setup
import logging
# Create a file handler
file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8')
# Configure basic settings
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(lineno)d - %(created)f: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
handlers=[file_handler],
level=logging.DEBUG
)
# Now you can log
logging.debug('This is a debug message')
Dictionary-Based Logging Configuration (Recommended)
Using a dictionary to configure logging is flexible and widely adopted. Below is a complete example.
import logging
import logging.config
# define format strings
standard_format = (
'[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s]'
'[%(filename)s:%(lineno)d][%(levelname)s][%(message)s]'
)
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
test_format = '%(asctime)s] %(message)s'
logfile_path = 'a3.log'
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
'test': {
'format': test_format
},
},
'filters': {},
'handlers': {
# console handler
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
# file handler for general logs with rotation
'default': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'formatter': 'standard',
'filename': logfile_path,
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'encoding': 'utf-8'
},
# another file handler with different format
'other': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'formatter': 'test',
'filename': 'a2.log',
'encoding': 'utf-8'
}
},
'loggers': {
# root logger (empty key) – handles all loggers by default
'': {
'handlers': ['default', 'console'],
'level': 'DEBUG',
'propagate': True
},
'other': {
'handlers': ['other'],
'level': 'DEBUG',
'propagate': False
}
}
}
# Apply configuration
logging.config.dictConfig(LOGGING_DIC)
logger1 = logging.getLogger('xxx')
logger1.debug('Stay calm and keep learning – effort always pays off')
Ultimate Logging Setup (Simplified)
A concise setup using basicConfig for smaller applications.
import logging
logging.basicConfig(
# 1. Output destination: terminal (default) or file
# filename='access.log', # uncomment to write to file
# 2. Format
format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
# 3. Time format
datefmt='%Y-%m-%d %H:%M:%S %p',
# 4. Log level (numeric values: CRITICAL=50, ERROR=40, WARNING=30, INFO=20, DEBUG=10)
level=30, # WARNING
)
# Output logs
logging.debug('Debug message')
logging.info('Info message')
logging.warning('Warning message')
logging.error('Error message')
logging.critical('Critical message')
Summary
- Use
basicConfigfor simple setups. - Use dictionary-based configuration (
dictConfig) for complex, production-ready systems. - Understand log levels and format placeholders to control output.
- Leverage handlers (StreamHandler, FileHandler, RotatingFileHandler) to route logs appropriately.