Python标准库-logging
一、为什么需要logging模块?
在Python开发中,print()是最简单的调试方式,但在生产环境中存在明显缺陷:
- 无法区分消息级别(调试/错误/警告)
- 没有时间戳记录
- 不能灵活输出到不同目标(文件/控制台/网络)
- 缺乏日志轮转等管理功能
logging模块作为Python标准库的一部分,提供了企业级的日志解决方案。根据CSDN技术文章评分标准,本文将从实际应用出发,深入讲解logging模块的各个功能点。
二、logging核心组件架构
import logging
# 组件关系示意图
"""
Loggers (暴露接口给应用代码)
|
Handlers (决定日志输出位置)
|
Filters (提供更细粒度的过滤)
|
Formatters (指定最终输出格式)
"""
三、基础使用模式
3.1 快速入门示例
import logging
# 基础配置(不推荐生产环境使用)
logging.basicConfig(level=logging.INFO)
# 记录不同级别日志
logging.debug("调试信息") # 不会输出
logging.info("程序正常运行")
logging.warning("潜在问题警告")
logging.error("严重错误发生")
logging.critical("致命错误")
3.2 推荐的标准用法
# 最佳实践:每个模块创建自己的logger
logger = logging.getLogger(__name__)
def process_data(data):
try:
logger.info(f"Processing {len(data)} items")
# ...处理逻辑...
except Exception as e:
logger.error(f"处理失败: {e}", exc_info=True)
四、高级配置技巧
4.1 详细配置示例
import logging
from logging.handlers import RotatingFileHandler
# 创建logger
logger = logging.getLogger("app")
logger.setLevel(logging.DEBUG)
# 创建文件处理器(自动轮转)
handler = RotatingFileHandler(
"app.log",
maxBytes=1024*1024, # 1MB
backupCount=5
)
handler.setLevel(logging.INFO)
# 创建控制台处理器
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
# 创建格式化器
formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
handler.setFormatter(formatter)
console.setFormatter(formatter)
# 添加处理器
logger.addHandler(handler)
logger.addHandler(console)
4.2 日志级别详解
级别 | 数值 | 使用场景 |
---|---|---|
DEBUG | 10 | 开发调试详细信息 |
INFO | 20 | 程序正常运行信息 |
WARNING | 30 | 潜在问题警告 |
ERROR | 40 | 严重错误 |
CRITICAL | 50 | 致命错误 |
五、生产环境最佳实践
5.1 日志过滤技巧
class SecurityFilter(logging.Filter):
def filter(self, record):
# 过滤敏感信息
if "password" in record.msg.lower():
return False
return True
logger.addFilter(SecurityFilter())
5.2 上下文信息记录
# 使用extra参数添加上下文
logger.info("用户操作", extra={
"user": "admin",
"ip": "192.168.1.1"
})
# 格式化器中添加对应字段
formatter = logging.Formatter(
"%(asctime)s [%(user)s@%(ip)s] %(message)s"
)
5.3 性能优化建议
-
避免在热路径中使用字符串格式化:
# 不推荐 logger.debug(f"Value: {expensive_function()}") # 推荐 if logger.isEnabledFor(logging.DEBUG): logger.debug("Value: %s", expensive_function())
-
使用QueueHandler实现异步日志:
from logging.handlers import QueueHandler, QueueListener import queue log_queue = queue.Queue(-1) queue_handler = QueueHandler(log_queue) logger.addHandler(queue_handler) # 单独线程处理日志 listener = QueueListener(log_queue, console_handler) listener.start()
六、常见问题解决方案
Q1: 日志文件不按预期轮转?
- 检查文件权限
- 确保maxBytes设置合理
- 确认没有多个handler冲突
Q2: 多模块日志配置混乱?
- 使用
__name__
获取logger - 在主模块统一配置,子模块直接获取logger
Q3: 如何捕获未处理异常?
import sys
def handle_exception(exc_type, exc_value, exc_traceback):
logger.critical("未捕获异常",
exc_info=(exc_type, exc_value, exc_traceback))
sys.excepthook = handle_exception
七、扩展应用场景
7.1 与Django集成
# settings.py
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"file": {
"level": "DEBUG",
"class": "logging.FileHandler",
"filename": "django.log",
},
},
"loggers": {
"django": {
"handlers": ["file"],
"level": "INFO",
},
},
}
7.2 日志监控报警
# 使用SMTPHandler发送错误邮件
from logging.handlers import SMTPHandler
mail_handler = SMTPHandler(
mailhost=("smtp.example.com", 587),
fromaddr="server@example.com",
toaddrs=["admin@example.com"],
subject="应用错误报警",
credentials=("user", "password")
)
mail_handler.setLevel(logging.ERROR)
logger.addHandler(mail_handler)
八、总结
正确使用logging模块可以显著提高应用的可维护性和问题诊断效率,是每个Python开发者必须掌握的核心技能。