📝 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'})

七、生产环境最佳实践

  1. 使用配置文件:将日志配置独立出来,便于调整
  2. 分级存储:DEBUG日志存文件,WARNING以上同时输出到控制台
  3. 敏感信息脱敏:使用Filter处理密码、token等敏感信息
  4. 异步日志:高并发场景使用QueueHandler避免IO阻塞
  5. 结构化日志:考虑使用JSON格式便于日志分析系统解析

八、总结

Python的logging模块是一个功能完备、设计精良的日志系统。从简单的basicConfig到复杂的dictConfig,它可以满足不同规模项目的需求。掌握logging的使用,能让你的程序更加专业、易于维护和调试。

记住:好的日志就像好的注释,它告诉你程序"在想什么",而不仅仅是"在做什么"。


参考资料:

  • Python官方文档 - Logging HOWTO
  • Python Cookbook - Advanced Logging
  • 12 Factor App - Logs
posted @ 2026-04-16 06:03  码小小小仙  阅读(43)  评论(0)    收藏  举报