Python 入门:用标准库写一个带轮转的日志小工具
刚学 Python 的人写脚本,习惯用 print 打日志。调试时挺顺手,但脚本上线之后问题就来了:print 没有时间戳,没有级别区分,输出还混在终端里,出了问题想回溯,只能两眼一抹黑。这时候就要请出标准库里的 logging 模块——不需要装任何第三方包,几行配置就能得到一套正经的日志系统。
一、logging 的三板斧:Logger、Handler、Formatter
logging 的核心其实只有三个概念:
- Logger:日志器,负责“记什么”。每个模块可以有自己的 logger,用
logging.getLogger(__name__)拿名字,避免和别人的日志搅在一起。 - Handler:处理器,负责“记到哪”。输出到控制台是
StreamHandler,写文件是FileHandler。 - Formatter:格式器,负责“长什么样”。比如
%(asctime)s - %(levelname)s - %(message)s就会打出时间、级别和内容。
再加上日志级别(DEBUG < INFO < WARNING < ERROR < CRITICAL),只有大于等于设定级别的消息才会被记录。开发时设 DEBUG,上线后设 INFO,一行代码切换噪音量。
二、让日志自动轮转:TimedRotatingFileHandler
脚本长期跑,日志文件会越写越大。标准库提供了两个现成的轮转处理器:按大小轮转的 RotatingFileHandler 和按时间轮转的 TimedRotatingFileHandler。对定时任务类脚本,按天轮转最省心:
import logging
from logging.handlers import TimedRotatingFileHandler
logger = logging.getLogger("myjob")
logger.setLevel(logging.INFO)
handler = TimedRotatingFileHandler(
"myjob.log", when="midnight", interval=1, backupCount=7, encoding="utf-8"
)
handler.setFormatter(logging.Formatter(
"%(asctime)s [%(levelname)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S"
))
logger.addHandler(handler)
logger.info("任务开始")
when="midnight" 表示每天午夜切分,backupCount=7 只保留最近 7 天的旧日志,磁盘不会被日志撑爆。旧文件会自动命名为 myjob.log.2026-10-22 这种形式,排查历史问题时按日期找就行。
三、封装一个开箱即用的小工具
每个脚本都写一遍配置太啰嗦,包成一个函数放工具模块里:
# mylog.py
import logging, os
from logging.handlers import TimedRotatingFileHandler
def get_logger(name, log_dir="logs", level=logging.INFO):
os.makedirs(log_dir, exist_ok=True)
logger = logging.getLogger(name)
if logger.handlers: # 避免重复添加
return logger
logger.setLevel(level)
file_h = TimedRotatingFileHandler(
os.path.join(log_dir, f"{name}.log"),
when="midnight", interval=1, backupCount=7, encoding="utf-8",
)
file_h.setFormatter(logging.Formatter(
"%(asctime)s [%(levelname)s] %(name)s: %(message)s"
))
console_h = logging.StreamHandler()
console_h.setFormatter(logging.Formatter("[%(levelname)s] %(message)s"))
logger.addHandler(file_h)
logger.addHandler(console_h)
return logger
业务脚本里只需要两行:
from mylog import get_logger
log = get_logger("crawler")
log.info("开始抓取第 1 页")
log.warning("第 3 页超时,重试中")
log.error("第 5 页失败,已跳过")
既写文件又打控制台,开发联调和线上排查都顾得到。
四、几个新手容易踩的坑
- root logger 污染:直接用
logging.info(...)走的是 root logger,库和业务日志会混在一起。养成getLogger(__name__)的习惯。 - 重复输出:handler 被添加多次,同一条日志会打好几遍。用上面的
if logger.handlers守卫,或者在配置前logger.handlers.clear()。 - 级别设错:
logger.setLevel和handler.setLevel是两道闸门,两个都要放行。最省事是只设 logger 的级别,handler 保持默认。 - 中文乱码:Windows 下写文件记得加
encoding="utf-8",否则中文日志打开是乱码。
小结
print 适合调试,logging 适合生产。从 print 换到 logging,成本就是学会 Logger/Handler/Formatter 三件套,再加一个轮转处理器。把 get_logger 收进自己的工具箱,以后每个脚本开局两行,日志规范一次到位。
- 点赞
- 收藏
- 关注作者
评论(0)