王芳的技术写作 —— 文档与分享

Python 日志模块 logging 的最佳实践

刚学 Python 时排错全靠 print,上线后才发现:print 的东西重定向到哪了?时间戳呢?日志级别呢?切到 logging 只需要改个习惯,收益巨大。这篇是我的常用模板。

基础配置:一次到位

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(name)s:%(lineno)d - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
log = logging.getLogger(__name__)

log.info("服务启动")
log.warning("磁盘使用率超过 80%")
log.error("数据库连接失败", exc_info=True)

exc_info=True 会自动把异常堆栈打出来,排错时救命。注意 getLogger(__name__) 用模块名,日志里能直接定位到哪个文件哪一行。

生产环境:按天切分 + 同时输出到文件

日志不能一直往一个文件里写,用 TimedRotatingFileHandler 按天切:

import logging
from logging.handlers import TimedRotatingFileHandler

log = logging.getLogger("myapp")
log.setLevel(logging.INFO)

fmt = logging.Formatter(
    "%(asctime)s [%(levelname)s] %(name)s:%(lineno)d - %(message)s"
)

# 每天一个文件,保留 30 天
fh = TimedRotatingFileHandler(
    "/var/log/myapp/app.log",
    when="midnight",
    backupCount=30,
    encoding="utf-8",
)
fh.setFormatter(fmt)
log.addHandler(fh)

# 同时输出到控制台,docker logs 能直接看到
ch = logging.StreamHandler()
ch.setFormatter(fmt)
log.addHandler(ch)

几个容易踩的坑

日志格式建议

我的格式固定包含:时间、级别、模块名、行号、消息。 structured logging(json 格式)更适合上 ELK 的场景,小项目文本格式够了,grep 起来方便。

print 是调试工具,logging 是工程工具。项目超过 500 行,就该换 logging 了。
← 返回首页