📝 Python日志记录logging模块配置与使用:从入门到生产环境
📝 Python日志记录logging模块配置与使用:从入门到生产环境
在Python开发中,日志记录是一个不可或缺的环节。无论是调试程序、追踪错误,还是监控生产环境的运行状态,日志都扮演着至关重要的角色。Python标准库中的logging模块提供了强大而灵活的日志记录功能,本文将带你从基础用法到高级配置,全面掌握这个模块。
一、为什么要使用logging而不是print?
很多初学者习惯使用print()来输出调试信息,但在生产环境中,这种方式存在诸多问题:
- 输出无法控制:print会直接输出到stdout,无法灵活配置
- 没有级别区分:无法区分调试信息、警告和错误
- 难以持久化:无法方便地写入文件或发送到远程服务器
- 无法格式化:输出格式固定,难以添加时间戳、行号等信息
而logging模块完美解决了这些问题,提供了分级、格式化、多输出目标等强大功能。
二、logging基础用法
1. 最简单的使用方式
import logging
# 默认级别是WARNING,只有WARNING及以上级别会输出
logging.debug('这是一条debug信息')
logging.info('这是一条info信息')
logging.warning('这是一条warning信息')
logging.error('这是一条error信息')
logging.critical('这是一条critical信息')
2. 基本配置
import logging
# 基本配置
logging.basicConfig(
level=logging.DEBUG, # 设置日志级别
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logging.info('程序启动成功')
三、日志级别详解
logging定义了5个标准日志级别,从低到高依次为:
| 级别 | 数值 | 使用场景 |
|---|---|---|
| DEBUG | 10 | 详细的调试信息,用于开发阶段 |
| INFO | 20 | 确认程序按预期运行 |
| WARNING | 30 | 警告,程序仍正常运行但需注意 |
| ERROR | 40 | 错误,程序某个功能无法执行 |
| CRITICAL | 50 | 严重错误,程序可能无法继续运行 |
四、高级配置:Handler、Formatter和Filter
1. 日志处理器(Handler)
Handler负责将日志发送到不同的目的地:
import logging
# 创建logger
logger = logging.getLogger('my_app')
logger.setLevel(logging.DEBUG)
# 文件处理器 - 记录所有日志
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.DEBUG)
# 控制台处理器 - 只显示警告及以上
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.WARNING)
# 添加处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
logger.debug('这条只写入文件')
logger.error('这条同时显示在控制台和文件')
2. 格式化器(Formatter)
# 详细格式
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s'
)
file_handler.setFormatter(formatter)
3. 常用Formatter格式说明
%(asctime)s- 时间戳%(name)s- logger名称%(levelname)s- 日志级别%(message)s- 日志消息%(filename)s- 源文件名%(lineno)d- 行号%(funcName)s- 函数名%(process)d- 进程ID%(thread)d- 线程ID
五、配置文件方式
1. 使用dictConfig(推荐)
import logging
import logging.config
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
},
'detailed': {
'format': '%(asctime)s [%(levelname)s] %(name)s [%(filename)s:%(lineno)d]: %(message)s'
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'standard',
'level': 'INFO',
},
'file': {
'class': 'logging.FileHandler',
'filename': 'app.log',
'formatter': 'detailed',
'level': 'DEBUG',
},
},
'loggers': {
'': { # root logger
'handlers': ['console', 'file'],
'level': 'DEBUG',
},
'urllib3': {
'level': 'WARNING', # 降低第三方库的日志级别
},
}
}
logging.config.dictConfig(LOGGING_CONFIG)
2. 从配置文件加载
# 从YAML文件加载
import yaml
with open('logging.yaml', 'r') as f:
config = yaml.safe_load(f)
logging.config.dictConfig(config)
六、高级技巧
1. 日志轮转
from logging.handlers import RotatingFileHandler
# 按文件大小轮转,单个文件最大1MB,保留5个备份
handler = RotatingFileHandler(
'app.log', maxBytes=1024*1024, backupCount=5
)
# 按时间轮转(每天一个文件)
from logging.handlers import TimedRotatingFileHandler
handler = TimedRotatingFileHandler(
'app.log', when='midnight', interval=1, backupCount=7
)
2. 异常信息记录
try:
result = 1 / 0
except Exception as e:
# 自动包含堆栈信息
logging.error('计算出错', exc_info=True)
# 或者
logging.exception('计算出错') # 等效于exc_info=True
3. 使用LoggerAdapter添加上下文
class ContextFilter(logging.Filter):
def filter(self, record):
record.user_id = getattr(record, 'user_id', 'anonymous')
return True
logger = logging.getLogger('my_app')
logger.addFilter(ContextFilter())
# 使用extra传递上下文
logger.info('用户操作', extra={'user_id': 'user_123'})
七、生产环境最佳实践
- 使用配置文件:将日志配置独立出来,便于调整
- 分级存储:DEBUG日志存文件,WARNING以上同时输出到控制台
- 敏感信息脱敏:使用Filter处理密码、token等敏感信息
- 异步日志:高并发场景使用QueueHandler避免IO阻塞
- 结构化日志:考虑使用JSON格式便于日志分析系统解析
八、总结
Python的logging模块是一个功能完备、设计精良的日志系统。从简单的basicConfig到复杂的dictConfig,它可以满足不同规模项目的需求。掌握logging的使用,能让你的程序更加专业、易于维护和调试。
记住:好的日志就像好的注释,它告诉你程序"在想什么",而不仅仅是"在做什么"。
参考资料:
- Python官方文档 - Logging HOWTO
- Python Cookbook - Advanced Logging
- 12 Factor App - Logs

浙公网安备 33010602011771号