Python 日志模块 logging 详解:怎么配才不是只打印到屏幕

小飞兽 Python 6 次阅读 2026-07-24

Introduction

很多 Python 代码里看到的是 print("debug info"),但生产环境代码里有 print 调试是大忌——生产服务器没有终端,打印什么用都没有。

Python 标准库的 logging 模块是解决这个问题的标准方案:分级别、可配置、能输出到文件/网络/邮件。

---

基础语法

1. 五个日志级别

import logging

logging.debug("调试信息")   # 10 - 详细
logging.info("一般信息")    # 20 - 正常运行
logging.warning("警告")     # 30 - 有问题但不影响功能
logging.error("错误")       # 40 - 功能受损
logging.critical("严重")   # 50 - 程序可能崩溃

默认级别是 WARNING,所以 DEBUG 和 INFO 默认不显示。

2. 基础配置:输出到文件

import logging

logging.basicConfig(
    level=logging.DEBUG,
    filename="app.log",
    filemode="a",
    format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)

logger = logging.getLogger(__name__)
logger.debug("这是一条调试日志")
logger.info("这是一般信息")

3. 多 Handler:同时输出到屏幕和文件

import logging

logger = logging.getLogger("myapp")
logger.setLevel(logging.DEBUG)

# 文件 Handler(记录所有级别)
file_handler = logging.FileHandler("app.log", encoding="utf-8")
file_handler.setLevel(logging.DEBUG)

# 控制台 Handler(只显示 WARNING 及以上)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.WARNING)

# 格式化
formatter = logging.Formatter(
    "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)

logger.addHandler(file_handler)
logger.addHandler(console_handler)

# 测试
logger.debug("调试信息")   # 只进文件
logger.warning("警告信息")  # 文件 + 屏幕都显示

4. 按模块分别配置日志级别

import logging
import mymodule

logging.basicConfig(level=logging.DEBUG)

# mymodule 里的 DEBUG 信息默认不显示
logging.getLogger("mymodule").setLevel(logging.DEBUG)

5. 日志轮转(RotatingFileHandler)

日志文件无限增长会撑爆磁盘。用 RotatingFileHandler 限制文件大小:

from logging.handlers import RotatingFileHandler

handler = RotatingFileHandler(
    "app.log",
    maxBytes=10 * 1024 * 1024,  # 10MB
    backupCount=5               # 保留5个备份
)
logger.addHandler(handler)

当日志文件超过 10MB,自动重命名 app.logapp.log.1,新建 app.log 继续写。

---

常见问题

Q1: 日志输出乱码?

FileHandlerencoding="utf-8"StreamHandler(sys.stderr)不需要。

Q2: 日志格式里的占位符?

| 占位符 | 说明 | |--------|------| | %(asctime)s | 时间 | | %(levelname)s | 日志级别 | | %(name)s | Logger 名称 | | %(message)s | 日志内容 | | %(filename)s | 文件名 | | %(lineno)d | 行号 |

Q3: logging.basicConfig 只生效一次?

basicConfig 对已创建 Logger 无效。在程序入口(if __name__ == "__main__" 之前)尽早配置。

Q4: 生产环境用什么日志级别?

  • DEBUG:本地开发调试
  • INFO:正常业务流程(如"用户登录成功")
  • WARNING:异常但能自动恢复(如"配置项缺失,使用默认值")
  • ERROR:功能受损(如"数据库连接失败")
  • CRITICAL:系统级故障

---

延伸阅读

  • [[Python 异常处理最佳实践]] — try/except 怎么写才合理
  • [[Python 单元测试里的日志]] — 测试时抑制/捕获日志
  • [[日志聚合工具 ELK]] — 用 Filebeat + Elasticsearch 收集生产日志

---
有问题欢迎在评论区交流!