生产环境脚本日志需用rotatingfilehandler轮转、模块级独立logger、loggeradapter注入上下文,避免basicconfig导致的覆盖、膨胀、混杂和丢失问题。

生产环境的脚本日志不能只靠 print 或简单 logging.basicConfig —— 它必须能区分模块、支持轮转、不丢日志、可追溯上下文,且不因日志失败导致主逻辑中断。
为什么 basicConfig 在生产中会失效
多数人用 logging.basicConfig(level=logging.INFO, filename="app.log") 启动日志,但一旦脚本被 systemd、cron 或容器反复拉起,或多个进程写同一文件,就会出现:
- 日志覆盖或错乱(多个进程同时写入)
- 文件无限增长,磁盘爆满
- 无法按模块/函数隔离日志源(比如
database.py和api.py混在一起) - 异常堆栈不完整(
exc_info=True没开,或没传给 handler)
用 RotatingFileHandler 控制日志体积和生命周期
直接替换 filename= 参数为带轮转能力的 handler,避免手动删旧日志:
import logging
from logging.handlers import RotatingFileHandler
<p>handler = RotatingFileHandler(
"script.log",
maxBytes=10 <em> 1024 </em> 1024, # 10MB
backupCount=5, # 最多保留 5 个历史文件
encoding="utf-8"
)
logger = logging.getLogger("my_script")
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)</p>
注意:maxBytes 是单个文件上限,不是总大小;backupCount=0 不清理旧文件,backupCount=1 只留当前 + 1 个备份 —— 别设太高,否则监控难发现磁盘隐患。
为每个模块单独配置 logger,避免 root logger 污染
全局 logging.getLogger()(即 root logger)一旦被第三方库修改 level 或 handler,你的日志就不可控。正确做法是:
- 每个模块用
logging.getLogger(__name__)获取独立 logger - 在入口脚本统一配置,不调用
basicConfig - 禁止在模块内调用
addHandler—— handler 只由主程序注册一次
例如 database.py 中:
import logging
logger = logging.getLogger(__name__) # 名为 "database"
<p>def connect():
logger.info("Connecting to DB...")
try:
...
except Exception as e:
logger.error("DB connection failed", exc_info=True) # 关键:带上堆栈</p>
添加 context 字段(如 task_id、host)让日志可追踪
自动化脚本常并发执行多个任务,纯时间戳+level 不足以定位问题。用 LoggerAdapter 注入上下文:
import logging
<p>class ContextAdapter(logging.LoggerAdapter):
def process(self, msg, kwargs):
return f"[{self.extra['task_id']}] {msg}", kwargs</p><p>logger = logging.getLogger("my_script")
adapter = ContextAdapter(logger, {"task_id": "task_20240521_abc123"})
adapter.info("Starting sync") # 输出:[task_20240521_abc123] Starting sync</p>
别用 Formatter 硬编码字段 —— 那样所有日志都带固定值;LoggerAdapter 允许每次调用动态传参。如果脚本跑在容器里,host 或 pod_name 也建议加进去,方便和监控系统对齐。
真正麻烦的不是加几行日志代码,而是确保 handler 不阻塞主线程、rotate 时不卡住、异常时 fallback 到 stderr 而不是静默丢失 —— 这些得在第一次部署前就验证好。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











