​​Python 日志模块 Logger 实战教程​

​本教程面向需要稳定、可维护日志系统的 ​​Python​​ 开发者,涵盖从基础用法到生产级最佳实践,帮助你快速掌握 ​​logging​​ 的核心概念、配置方式与进阶技巧。

​一 基础概念与日志级别​

  • ​Logger(记录器)​​:应用代码直接调用的接口,负责产生日志;可通过名称分层(如 ​​a.b​​ 是 ​​a​​ 的子记录器)。
  • ​Handler(处理器)​​:决定日志去向,如 ​​StreamHandler​​(控制台)、​​FileHandler​​(文件)、以及按大小/时间轮转的 ​​RotatingFileHandler​​、​​TimedRotatingFileHandler​​。
  • ​Formatter(格式化器)​​:定义日志输出样式,如时间、文件名、行号、级别、消息等。
  • ​Filter(过滤器)​​:更细粒度的输出控制,可在记录器或处理器上设置。
  • 日志级别(由低到高):​​DEBUG​​、​​INFO​​、​​WARNING​​、​​ERROR​​、​​CRITICAL​​;默认阈值是 ​​WARNING​​,只有大于等于该级别的日志才会被输出。

​二 快速上手与基本配置​

  • 最简用法(直接使用默认的 ​​root Logger​​):
import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)

logging.debug("调试信息")
logging.info("程序启动")
logging.warning("磁盘空间偏低")
logging.error("数据库连接失败")
logging.critical("服务不可用")
  • 将日志写入文件(覆盖模式):
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    filename="app.log",
    filemode="w",  # 'a' 为追加
    datefmt="%Y-%m-%d %H:%M:%S"
)
logging.info("日志已写入文件")
  • 说明:
    • ​basicConfig​​ 仅在没有处理器附加到 ​​root Logger​​ 时生效,适合做一次性基础配置。
    • 常用格式字段:​​%(asctime)s​​、​​%(name)s​​、​​%(levelname)s​​、​​%(message)s​​、​​%(filename)s​​、​​%(lineno)d​​、​​%(funcName)s​​、​​%(thread)d​​、​​%(process)d​​。

​三 自定义 Logger 与同时输出到控制台和文件​

  • 推荐做法:为每个模块创建独立的 ​​Logger​​(名称使用 ​​__name__​​),并通过多个 ​​Handler​​ 分发到不同目标,且可为不同 Handler 设置不同级别。
  • 示例:控制台输出 ​​INFO​​ 及以上,文件记录 ​​DEBUG​​ 及以上,并包含行号与文件名。
import logging

def get_logger(name=__name__, level=logging.DEBUG):
    logger = logging.getLogger(name)
    logger.setLevel(level)

    if logger.handlers:  # 避免重复添加处理器
        return logger

    # 控制台处理器:INFO 及以上
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)
    ch_fmt = logging.Formatter(
        "[%(levelname)-8s] %(name)s:%(lineno)4d | %(message)s"
    )
    ch.setFormatter(ch_fmt)

    # 文件处理器:DEBUG 及以上(自动创建日志文件)
    fh = logging.FileHandler("debug.log", encoding="utf-8")
    fh.setLevel(logging.DEBUG)
    fh_fmt = logging.Formatter(
        "%(asctime)s | %(name)s | %(levelname)-8s | %(filename)s:%(lineno)d | %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S"
    )
    fh.setFormatter(fh_fmt)

    logger.addHandler(ch)
    logger.addHandler(fh)
    logger.propagate = False  # 阻止向父记录器传播,避免重复输出
    return logger

# 使用示例
if __name__ == "__main__":
    log = get_logger()
    log.debug("调试信息,仅写入文件")
    log.info("业务处理开始")
    log.warning("这是一个警告")
    try:
        1 / 0
    except Exception:
        log.exception("发生异常,自动附带堆栈")
  • 关键点:
    • 使用 ​​get_logger(name)​​ 形成层级,便于定位来源模块。
    • 通过 ​​logger.setLevel​​ 与 ​​handler.setLevel​​ 的组合,实现“记录更细、输出更精”的效果。
    • 设置 ​​logger.propagate = False​​ 可避免在多模块场景下出现重复日志。

​四 日志轮转与归档​

  • 按文件大小轮转(​​RotatingFileHandler​​):当日志达到 ​​maxBytes​​ 时滚动,保留 ​​backupCount​​ 个旧文件。
from logging.handlers import RotatingFileHandler

handler = RotatingFileHandler(
    "app.log", maxBytes=1024 * 1024, backupCount=5, encoding="utf-8"
)
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter(
    "%(asctime)s | %(levelname)s | %(message)s"
))
logging.getLogger().addHandler(handler)
  • 按时间轮转(​​TimedRotatingFileHandler​​):可按 ​​S/M/H/D/W0–W6/midnight​​ 等间隔滚动。
from logging.handlers import TimedRotatingFileHandler

handler = TimedRotatingFileHandler(
    "app.log", when="midnight", interval=1, backupCount=7, encoding="utf-8"
)
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter(
    "%(asctime)s | %(levelname)s | %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
))
logging.getLogger().addHandler(handler)
  • 建议:生产环境务必启用轮转,配合合理的 ​​maxBytes​​ 与 ​​backupCount​​,避免磁盘被占满。

​五 多模块项目组织与最佳实践​

  • 多模块组织(推荐在每个模块中使用 ​​__name__​​ 获取记录器):
# util.py
import logging
log = logging.getLogger(__name__)

def work():
    log.info("工具模块执行中")

# main.py
import logging
import util

log = logging.getLogger(__name__)
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)

log.info("主程序启动")
util.work()
log.info("主程序结束")
  • 执行顺序与传播:子记录器的日志会向上传播到父记录器;若父子记录器都配置了处理器,可能产生重复输出,可通过 ​​logger.propagate = False​​ 控制。
  • 配置方式选择:
    • 小项目:使用 ​​basicConfig​​ 或在主模块集中配置。
    • 中大型项目:使用 ​​logging.config.dictConfig​​ 或 ​​YAML​​ 配置文件,便于维护与环境隔离。
  • 常见坑与建议:
    • 避免在库代码中调用 ​​basicConfig​​(应由应用入口统一配置)。
    • 避免重复添加处理器(可在添加前检查 ​​logger.handlers​​)。
    • 统一日志格式,包含 ​​时间、模块名、行号、级别​​,便于检索与定位。
    • 生产环境关闭 ​​DEBUG​​,或按环境动态调整级别。
    • 敏感信息(如密码、Token)不要写入日志。
    • 异常堆栈使用 ​​logger.exception(...)​​ 自动记录。
    • 多进程场景需使用支持多进程的处理器(如队列处理器或第三方方案)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值