
别再用print调试了!Python Logging模块帮你省50%排错时间
本文最后更新于 2025-09-10,文章内容可能已经过时。
别再用print调试了!Python Logging模块帮你省50%排错时间
一、先问个扎心的问题:你还在这么做日志吗?
如果你写 Python 时,遇到这些场景会头疼,那这篇文章就是为你写的:
-
调试时用
print("这里到了")
,上线前要手动删 / 注释掉,漏一个就尴尬; -
线上程序报错,只知道 “有问题”,不知道是哪个模块、什么时间、具体上下文触发的;
-
想把日志存到文件,又想在控制台看实时输出,结果写了一堆
with open(...)
代码。
其实 Python 自带的logging
模块,早就把这些问题解决了 —— 而且不用装任何第三方库。
二、5 分钟上手:最实用的 3 个基础操作
1. 替代 print:让日志自带 “时间 + 级别”
先抛掉复杂配置,从最简单的开始。用logging
打印一条日志,比 print 多带了时间和日志级别(比如 INFO、ERROR),排错时一眼就知道什么时候发生了什么:
import logging
\# 第一步:配置基础日志(只需要写一次)
logging.basicConfig(
  level=logging.INFO, # 日志级别:DEBUG < INFO < WARNING < ERROR < CRITICAL
  format="%(asctime)s - %(levelname)s - %(message)s" # 日志格式:时间+级别+内容
)
\# 第二步:用日志替代print
logging.debug("这是调试信息,比如变量值:x=10") # 不会显示(因为level设为INFO)
logging.info("程序启动成功,开始处理数据") # 会显示:2024-05-20 14:30:00,123 - INFO - 程序启动成功...
logging.error("读取文件失败!路径:./data.csv") # 会显示,还能标红(部分终端支持)
👉 关键区别:print
是 “无脑输出”,logging
能帮你按 “重要程度” 过滤日志 —— 比如上线时把level
改成WARNING
,就只看警告和错误,不看琐碎的调试信息。
2. 把日志存到文件:再也不怕程序崩了没记录
如果程序在服务器上跑,控制台日志关了就没了。用filename
参数让日志自动存到文件,还能设置文件大小 / 备份(避免日志文件占满硬盘):
logging.basicConfig(
  level=logging.INFO,
  format="%(asctime)s - %(module)s - %(levelname)s - %(message)s", # 多加个“模块名”
  filename="app.log", # 日志存到这个文件
  filemode="a", # 追加模式(避免覆盖旧日志)
  encoding="utf-8" # 解决中文乱码问题
)
\# 测试:这行日志会同时显示在控制台+写入app.log
logging.error("用户登录失败:用户名不存在")
打开app.log
文件,会看到这样的内容,比纯控制台输出好追溯多了:
2024-05-20 14:35:00,456 - login - ERROR - 用户登录失败:用户名不存在
3. 多模块协作:日志能分清 “谁在报错”
如果你写的项目有多个文件(比如main.py
调用utils.py
),logging
能自动标明日志来自哪个模块,不用你手动加注释:
\# utils.py
import logging
def read\_file(path):
  try:
  with open(path) as f:
  return f.read()
  except Exception as e:
  logging.error(f"读取文件出错:{e}", exc\_info=True) # exc\_info=True:显示完整报错栈
\# main.py
import logging
import utils
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(module)s - %(message)s")
utils.read\_file("./nonexistent.txt") # 调用不存在的文件,触发错误
日志会清晰显示 “错误来自 utils 模块”,连报错栈都有,定位问题超快:
2024-05-20 14:40:00,789 - utils - 读取文件出错:\[Errno 2] No such file or directory: './nonexistent.txt'
Traceback (most recent call last):
  File "utils.py", line 4, in read\_file
  with open(path) as f:
FileNotFoundError: \[Errno 2] No such file or directory: './nonexistent.txt'
三、坦白说:Logging 模块的 3 个 “坑”,新手很容易踩
虽然logging
好用,但它不是完美的 —— 这些缺点我踩过,提前告诉你省时间:
1. 默认配置太 “简陋”,自定义要学一堆概念
basicConfig
只能应付简单场景,想做 “同时输出到控制台和文件”“按日期分割日志(比如每天一个文件)”,就得学Logger
、Handler
、Formatter
这些概念,新手容易绕晕:
- 比如你想 “控制台显示 INFO 以上,文件存 DEBUG 以上”,得手动创建两个
Handler
,再绑定到Logger
上,代码比basicConfig
复杂 3 倍。
2. 多线程 / 多进程下可能丢日志
如果你的程序用了多线程(比如threading
)或多进程(比如multiprocessing
),直接用logging
可能会丢日志 —— 比如两个线程同时写日志,会出现日志内容重叠、甚至部分日志没写进去的情况。
👉 解决办法:需要手动加锁(比如用logging.handlers.QueueHandler
),但又要多写一堆代码,不够 “开箱即用”。
3. 配置文件写起来麻烦
如果项目大了,不想把日志配置写在代码里(想单独放个log.conf
文件),logging
支持的配置格式(比如 INI、JSON)都不太友好:
-
INI 格式要记一堆
[loggers]
[handlers]
节点,写错一个逗号就生效不了; -
JSON 格式虽然熟悉,但嵌套层级多,看着就累。
四、进阶技巧:让 Logging 用起来更爽
1. 用dictConfig
简化复杂配置
不想记Handler
的创建步骤?用dictConfig
把配置写成字典,结构更清晰,复制粘贴就能用(比如 “控制台 + 文件双输出”):
import logging.config
log\_config = {
  "version": 1,
  "disable\_existing\_loggers": False,
  "formatters": { # 定义日志格式
  "standard": {"format": "%(asctime)s - %(module)s - %(levelname)s - %(message)s"}
  },
  "handlers": { # 定义两个Handler:控制台+文件
  "console": {
  "class": "logging.StreamHandler",
  "level": "INFO",
  "formatter": "standard"
  },
  "file": {
  "class": "logging.FileHandler",
  "level": "DEBUG",
  "formatter": "standard",
  "filename": "app.log",
  "encoding": "utf-8"
  }
  },
  "root": { # 根Logger,把两个Handler加进来
  "level": "DEBUG",
  "handlers": \["console", "file"]
  }
}
\# 加载配置
logging.config.dictConfig(log\_config)
\# 测试:会同时输出到控制台和文件
logging.debug("调试信息:用户ID=123")
logging.error("数据库连接超时")
2. 嫌麻烦?试试第三方替代:Loguru
如果觉得logging
配置太繁琐,推荐用loguru
(需要pip install loguru
)—— 它把logging
的复杂逻辑封装了,一行代码就能实现 “控制台 + 文件 + 按日期分割”:
from loguru import logger
\# 一行配置:输出到控制台+每天一个日志文件(保留30天)
logger.add("app\_{time:YYYY-MM-DD}.log", rotation="1 day", retention=30, encoding="utf-8")
logger.info("程序启动")
logger.error("数据处理失败")
👉 缺点:如果项目已经用了logging
,替换起来要改不少代码,适合新项目起步用。
最后:总结一下什么时候用 Logging
-
写小脚本调试:用
print
没问题(快); -
项目超过 2 个文件、要上线、需要追溯错误:一定要用
logging
; -
觉得
logging
配置麻烦、新项目:试试loguru
。
你之前用print
踩过什么坑?或者logging
有什么没搞懂的地方?评论区聊聊~
(注:文档部分内容可能由 AI 生成)