Python应用日志管理:自动化按日期分割日志的完整指南

Python 应用日志管理:自动化按日期分割日志的完整指南(2025-2026 实用版)

目前生产环境中按日期(或按大小+日期)分割日志仍然是最主流、最可靠的做法。下面给出从简单到生产可用的完整方案梯度。

方案对比(按复杂度与适用场景)

方案是否依赖第三方库是否真正“每天一个文件”支持压缩旧日志适合场景推荐指数
logging + TimedRotatingFileHandler否(标准库)是(可精确到分钟)否(需额外脚本)中小型项目、快速上手★★★★☆
logging + TimedRotatingFileHandler + gzip 脚本是(延迟压缩)大多数中小型线上服务★★★★★
loguru + rotation=”每天” + retention是(loguru)是(内置)追求简洁、现代风格的项目★★★★☆
structlog + structlog-processors + 自定义 rotator可配合需要结构化日志 + JSON 的微服务★★★☆☆
业务层手动 + os.rename / shutil.move是(但代码侵入性强)可配合极致控制需求、特殊格式★★☆☆☆

推荐方案排序(2026 年视角)

  1. 中小型项目 / 想最快上线 → TimedRotatingFileHandler + 延迟压缩脚本
  2. 追求代码简洁、现代感 → loguru(强烈推荐新项目)
  3. 已有 structlog / 必须结构化 JSON 日志 → structlog + 自定义轮转
  4. 极致性能 / 不想任何依赖 → 标准库 + 外部 logrotate(容器/K8s 场景常见)

一、最推荐生产方案:标准库 + 延迟压缩(最稳)

# logger.py
import logging
from logging.handlers import TimedRotatingFileHandler
import os
import gzip
import shutil
from datetime import datetime, timedelta

LOG_DIR = "logs"
os.makedirs(LOG_DIR, exist_ok=True)

class GzipRotator:
    def __call__(self, default_name):
        # 当轮转发生时,把昨天的文件改名 + 压缩
        yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
        src = f"{default_name}.{yesterday}"
        dst = f"{src}.gz"

        if os.path.exists(src) and not os.path.exists(dst):
            with open(src, 'rb') as f_in:
                with gzip.open(dst, 'wb') as f_out:
                    shutil.copyfileobj(f_in, f_out)
            os.remove(src)  # 删除原文件,节省空间

# 配置
handler = TimedRotatingFileHandler(
    filename=os.path.join(LOG_DIR, "app.log"),
    when="midnight",           # 每天 00:00 轮转
    interval=1,
    backupCount=0,             # 不自动删除旧文件(我们自己管)
    encoding="utf-8"
)

# 关键:自定义轮转后的文件名处理(加 .gz)
handler.rotator = GzipRotator()

formatter = logging.Formatter(
    '%(asctime)s [%(levelname)s] %(name)s:%(lineno)d - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)
handler.setFormatter(formatter)

logger = logging.getLogger("myapp")
logger.setLevel(logging.INFO)
logger.addHandler(handler)

# 控制台也输出(开发方便)
console = logging.StreamHandler()
console.setFormatter(formatter)
logger.addHandler(console)

使用方式:

from logger import logger

logger.info("用户登录成功", extra={"user_id": 12345, "ip": "1.2.3.4"})
logger.error("数据库连接失败", exc_info=True)

结果文件结构示例:

logs/
├── app.log                ← 今天正在写的
├── app.log.2025-01-23.gz  ← 昨天的,已压缩
├── app.log.2025-01-22.gz
...

二、更现代、更简洁的选择:loguru(强烈推荐新项目)

# logger.py
from loguru import logger
import sys
from datetime import datetime

# 删除旧的默认 handler
logger.remove()

# 每天一个文件,保留 30 天,超过 500MB 也轮转,旧文件自动压缩
logger.add(
    "logs/app_{time:YYYY-MM-DD}.log",
    rotation="00:00",           # 每天 0 点轮转
    retention="30 days",        # 保留 30 天
    compression="zip",          # 或 "gz", "tar.gz"
    level="INFO",
    encoding="utf-8",
    enqueue=True,               # 异步写,性能更好
    backtrace=True,
    diagnose=True
)

# 同时输出到控制台(带颜色)
logger.add(
    sys.stdout,
    format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
    level="DEBUG" if os.getenv("DEBUG") else "INFO",
    colorize=True
)

# 使用(几乎和 print 一样方便)
logger.info("用户登录", user_id=12345, ip="1.2.3.4")
logger.exception("出错了")   # 自动带 traceback

loguru 最大优势:一行配置搞定轮转、压缩、保留、结构化输出。

三、生产环境额外建议(别忘了)

  1. 容器/K8s 环境
  • 首选把日志输出到 stdout/stderr,让容器编排系统(fluentbit / filebeat / vector)收集
  • 如果非要写文件 → sidecar 方式 + logrotate
  1. logrotate 方案(不改代码)(经典且可靠)
# /etc/logrotate.d/myapp
/var/app/logs/app.log {
    daily
    rotate 30
    missingok
    dateext
    dateformat -%Y-%m-%d
    compress
    delaycompress
    copytruncate        # 重要:不重启应用也能切割
    su appuser appgroup
}
  1. 结构化日志(推荐 JSON 格式)
# loguru JSON 示例
logger.add(
    "logs/app_{time:YYYY-MM-DD}.json",
    format="{time} {level} {message}",
    serialize=True,   # 输出 JSON
    rotation="00:00",
    retention="90 days",
    compression="zip"
)

快速选择表(直接抄作业)

需求推荐方案核心代码行数
最快上手、零配置loguru8–12 行
完全不引入第三方包TimedRotating + gzip25–35 行
必须 JSON 结构化 + 微服务structlog + JSON20–40 行
K8s / Docker 不写文件stdout + fluentbit0 行(业务)
已有 logrotate 基础设施标准 logging + copytruncate10 行

你当前的项目属于哪种情况?

  • 还在用 print / logging.basicConfig?
  • 已经用了 loguru / structlog?
  • 是 Docker / K8s 环境?
  • 需要 JSON 格式给 ELK / Loki?

告诉我你的具体场景,我可以给你最贴合的一份完整配置代码。

文章已创建 4050

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部