Python 日志模块 logging 详解:怎么配才不是只打印到屏幕
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.log → app.log.1,新建 app.log 继续写。
---
常见问题
Q1: 日志输出乱码?
FileHandler 加 encoding="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 收集生产日志
---
有问题欢迎在评论区交流!