📝 本章学习目标:本章聚焦企业级 Python 项目开发规范,帮助读者从零彻底掌握 logging 模块的使用、配置、封装与落地。通过本章学习,你将能独立搭建可复用、可监控、可持久化、多环境兼容的日志体系,全面替代 print 调试,满足线上项目运维、排查、审计与日志采集需求。
一、引言:为什么 logging 是项目第一必备模块
1.1 背景与意义
💡 核心认知:在真实企业项目中,日志是系统的 “黑匣子”。没有规范日志,等于线上程序 “裸奔”。
Python 自带的 print() 只能简单输出,无法满足:
- 日志分级(debug/info/warn/error)
- 持久化落地(写入文件、按大小 / 时间切割)
- 多模块统一输出
- 日志格式标准化(时间、文件名、行号、级别、信息)
- 对接 ELK、 Loki、云监控等采集系统
- 生产环境动态开关调试信息
- 异常堆栈完整捕获
logging 是 Python 官方内置、零依赖、生产级稳定的日志库,是所有后端、爬虫、数据分析、AI 工程化项目的基础基建。据行业实践统计:规范日志能让故障排查效率提升 10 倍以上。
1.2 本章结构概览
为了帮助你系统性掌握,本章按以下路线展开:
plaintext
📊 概念解析 → 核心组件 → 使用方法 → 高级配置 → 企业封装 → 实战案例 → 最佳实践 → 总结展望
二、核心概念解析
2.1 基本定义
概念一:logging 模块
- Python 官方标准库,无需安装,直接 import 使用。
- 支持日志级别、日志输出、格式控制、滚动切割、多处理器。
- 可同时输出到控制台、文件、网络、消息队列等多个目的地。
概念二:日志核心能力
表格
| 能力 | 说明 | 企业必备 |
|---|---|---|
| 级别控制 | 区分 debug/info/warning/error/critical | ✅ |
| 格式定制 | 时间、路径、行号、进程、线程 | ✅ |
| 持久化 | 写入文件并自动切割 | ✅ |
| 多 handler | 同时控制台 + 文件 + 远程 | ✅ |
| 全局单例 | 跨模块共享同一日志配置 | ✅ |
2.2 关键术语解释
⚠️ 注意:以下术语是理解 logging 的基础,请务必掌握。
术语 1:日志级别(Level)
DEBUG:调试信息,开发环境用INFO:普通运行信息,正常流程WARNING:警告,不影响运行但需注意ERROR:错误,函数 / 请求失败CRITICAL:严重错误,系统崩溃
术语 2:核心组件
- Logger:日志器,提供调用接口
- Handler:处理器,控制输出位置(控制台 / 文件)
- Formatter:格式器,定义输出样式
- Filter:过滤器,精细化过滤日志
2.3 技术架构概览
💡 架构理解:
plaintext
┌─────────────────────────────────────────┐
│ 业务调用层 │
│ logger.info()/error() 等 │
├─────────────────────────────────────────┤
│ Logger 日志器 │
│ 负责级别过滤与分发 │
├─────────────────────────────────────────┤
│ Handler 处理器 │
│ StreamHandler / FileHandler 等 │
├─────────────────────────────────────────┤
│ Formatter 格式器 │
│ 时间、级别、文件名、行号、内容 │
└─────────────────────────────────────────┘
三、技术原理深入
3.1 核心组件原理
组件一:Logger(日志器)
python
运行
import logging
# 获取日志器(全局单例)
logger = logging.getLogger(__name__)
# 设置最低级别
logger.setLevel(logging.DEBUG)
作用:接收日志、按级别过滤、分发给 Handler。
组件二:Handler(输出器)
常用:
- StreamHandler:控制台输出
- FileHandler:文件输出
- RotatingFileHandler:按大小切割
- TimedRotatingFileHandler:按时间切割
组件三:Formatter(格式器)
python
运行
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(filename)s - %(lineno)d - %(message)s'
)
组件四:Filter(过滤器)
用于更细粒度控制日志输出,一般项目较少使用。
3.2 基础使用流程
📊 标准流程:
- 获取 logger
- 设置级别
- 创建 Handler
- 设置 Formatter
- 添加 Handler 到 logger
- 输出日志
最简可运行代码
python
运行
import logging
# 1. 基本配置
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='run.log'
)
# 2. 输出日志
logging.debug('调试信息')
logging.info('程序启动成功')
logging.warning('磁盘空间不足')
logging.error('数据库连接失败')
logging.critical('服务崩溃!')
3.3 高级配置原理
按文件大小切割
python
运行
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
'app.log',
maxBytes=1024*1024*5, # 5MB
backupCount=5, # 保留5个文件
encoding='utf-8'
)
按时间切割(企业最常用)
python
运行
from logging.handlers import TimedRotatingFileHandler
handler = TimedRotatingFileHandler(
'run.log',
when='midnight', # 每天凌晨切割
interval=1,
backupCount=7, # 保留7天
encoding='utf-8'
)
四、实践应用指南
4.1 应用场景分析
✅ 核心场景:logging 在企业中的必备场景
场景一:后端 API 服务(FastAPI/Flask/Django)
- 记录请求路径、参数、返回值、耗时
- 记录数据库异常、第三方接口调用失败
- 按天切割,对接 ELK
场景二:数据处理 / AI 训练
- 记录数据读取、清洗进度
- 记录模型指标、loss、异常样本
- 保存关键节点信息,便于复现
场景三:定时任务 / 爬虫
- 记录启动、执行、结束状态
- 记录失败任务、重试次数
- 长期运行必须落地日志
场景四:多模块大型项目
- 统一日志格式、统一文件输出
- 全局共享 logger,避免混乱
4.2 实施步骤详解
🔧 企业标准实施步骤:
步骤一:确定日志规范① 输出格式(时间、级别、文件名、行号、信息)② 级别规则(dev=DEBUG,prod=INFO)③ 切割策略(按天 / 按大小)④ 保存时长(7 天 / 30 天)⑤ 输出位置(控制台 + 文件)
步骤二:技术选型清单
plaintext
## logging 技术选型清单
### 核心组件
- [ ] Logger:全局单例
- [ ] StreamHandler:控制台输出
- [ ] TimedRotatingFileHandler:按天切割
- [ ] Formatter:统一格式
### 增强能力
- [ ] 编码 utf-8
- [ ] 堆栈捕获
- [ ] 多环境兼容
- [ ] 重复 Handler 去重
步骤三:开发实现
表格
| 任务 | 描述 | 时间 |
|---|---|---|
| 基础配置 | basicConfig 快速使用 | 0.5 小时 |
| 高级封装 | 单例 logger 函数 / 类 | 1 小时 |
| 多模块集成 | 跨文件导入使用 | 1 小时 |
| 异常捕获 | 完整堆栈记录 | 1 小时 |
| 测试验证 | 分级输出、切割、编码 | 1 小时 |
4.3 最佳实践分享
💡 经验总结:最佳实践一:全局单例原则① 一个项目只创建一个 logger② 避免重复添加 Handler③ 所有模块导入同一个 logger
最佳实践二:分级规范
- DEBUG:开发调试
- INFO:启动、成功、流程正常
- WARNING:配置问题、资源不足
- ERROR:业务异常、调用失败
- CRITICAL:系统不可用
最佳实践三:生产禁忌
- 禁止用 print
- 禁止输出敏感信息(密码、密钥)
- 禁止无限大小日志文件
- 必须切割、必须压缩、必须定期清理
五、超多代码示例(从入门到企业级)
示例 1:最简控制台输出
python
运行
import logging
# 基础配置
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s - %(levelname)s - %(message)s"
)
# 测试输出
logging.debug("调试信息")
logging.info("普通信息")
logging.warning("警告信息")
logging.error("错误信息")
logging.critical("严重错误")
示例 2:日志输出到文件
python
运行
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
filename="app.log", # 输出文件
filemode="a", # 追加模式
encoding="utf-8"
)
logging.info("程序启动成功")
logging.error("数据库连接失败")
示例 3:同时输出到控制台 + 文件
python
运行
import logging
logger = logging.getLogger("test")
logger.setLevel(logging.DEBUG)
logger.handlers.clear() # 清空已有处理器
# 控制台处理器
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)
# 文件处理器
fh = logging.FileHandler("app.log", encoding="utf-8")
fh.setLevel(logging.INFO)
# 格式
formatter = logging.Formatter("%(asctime)s | %(levelname)s | %(message)s")
sh.setFormatter(formatter)
fh.setFormatter(formatter)
logger.addHandler(sh)
logger.addHandler(fh)
# 测试
logger.debug("这是调试信息(只在控制台)")
logger.info("这是普通信息(控制台+文件)")
示例 4:按文件大小自动切割
python
运行
import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger("size_rotate")
logger.setLevel(logging.INFO)
logger.handlers.clear()
# 每 5MB 切割一个文件
handler = RotatingFileHandler(
"rotate.log",
maxBytes=5*1024*1024, # 5MB
backupCount=5, # 最多保留5个
encoding="utf-8"
)
formatter = logging.Formatter("%(asctime)s | %(levelname)s | %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
# 测试
for i in range(1000):
logger.info(f"测试日志 {i}")
示例 5:按时间自动切割(企业首选)
python
运行
import logging
from logging.handlers import TimedRotatingFileHandler
logger = logging.getLogger("time_rotate")
logger.setLevel(logging.INFO)
logger.handlers.clear()
# 每天凌晨切割,保留7天
handler = TimedRotatingFileHandler(
"time.log",
when="midnight",
interval=1,
backupCount=7,
encoding="utf-8"
)
formatter = logging.Formatter("%(asctime)s | %(levelname)s | %(filename)s | %(lineno)d | %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.info("程序启动")
logger.warning("磁盘空间不足")
logger.error("接口调用失败")
示例 6:捕获异常堆栈信息
python
运行
import logging
logging.basicConfig(
level=logging.ERROR,
format="%(asctime)s | %(levelname)s | %(message)s",
filename="error.log",
encoding="utf-8"
)
try:
a = 1 / 0
except Exception as e:
logging.exception("发生除零错误") # 自动打印堆栈
示例 7:多模块共用日志
python
运行
# ------------------- log_config.py -------------------
import logging
def get_logger():
logger = logging.getLogger("project")
if logger.handlers:
return logger
logger.setLevel(logging.DEBUG)
sh = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s | %(levelname)s | %(message)s")
sh.setFormatter(formatter)
logger.addHandler(sh)
return logger
# ------------------- module_a.py -------------------
from log_config import get_logger
logger = get_logger()
def test():
logger.info("A模块运行")
# ------------------- main.py -------------------
from log_config import get_logger
import module_a
logger = get_logger()
logger.info("主程序启动")
module_a.test()
示例 8:显示文件名 + 行号 + 函数名(企业标准格式)
python
运行
import logging
logger = logging.getLogger("detail")
logger.setLevel(logging.DEBUG)
logger.handlers.clear()
sh = logging.StreamHandler()
formatter = logging.Formatter(
"%(asctime)s | %(levelname)-8s | %(filename)-15s | %(funcName)-10s | %(lineno)3d | %(message)s"
)
sh.setFormatter(formatter)
logger.addHandler(sh)
def test():
logger.debug("进入函数")
logger.info("执行成功")
test()
六、企业级实战案例
6.1 成功案例:企业级通用日志封装(可直接上线)
背景某 Python 后端项目需要统一日志:控制台 + 按天切割、多模块共用、兼容开发 / 生产环境。
解决方案(完整代码 + 逐行注释)
python
运行
# -*- coding: utf-8 -*-
"""
企业级 logging 封装
支持:控制台输出 + 按天切割 + 全局单例 + 中文不乱码
"""
import os
import logging
from logging.handlers import TimedRotatingFileHandler
from typing import Optional
def get_logger(name: str = __name__, log_dir: str = "logs") -> logging.Logger:
"""
企业级日志获取函数(全局单例)
:param name: 日志器名称
:param log_dir: 日志保存目录
:return: 配置好的 logger
"""
# 如果日志器已存在,直接返回,避免重复添加 Handler
logger = logging.getLogger(name)
if logger.handlers:
return logger
# ===================== 1. 基础配置 =====================
# 日志级别:开发DEBUG,生产INFO
logger.setLevel(logging.DEBUG)
# 避免日志向上传递到根日志器
logger.propagate = False
# ===================== 2. 创建日志目录 =====================
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# ===================== 3. 日志格式 =====================
# 时间 - 日志器名 - 级别 - 文件名 - 行号 - 信息
formatter = logging.Formatter(
"%(asctime)s | %(name)-12s | %(levelname)-8s | %(filename)-15s | %(lineno)4d | %(message)s"
)
# ===================== 4. 控制台 Handler =====================
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# ===================== 5. 文件 Handler(按天切割) =====================
log_file = os.path.join(log_dir, "app.log")
file_handler = TimedRotatingFileHandler(
filename=log_file,
when="midnight", # 每天凌晨切割
interval=1,
backupCount=7, # 保留7天
encoding="utf-8", # 中文不乱码
delay=True
)
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
# ===================== 全局单例 logger =====================
logger = get_logger("project")
# ===================== 使用示例 =====================
if __name__ == '__main__':
logger.debug("调试模式:参数详细信息")
logger.info("服务启动成功")
logger.warning("配置文件使用默认值")
logger.error("数据库连接超时")
logger.critical("磁盘已满,服务退出")
# 异常捕获示例
try:
1 / 0
except Exception as e:
logger.exception("发生除零异常") # 自动打印堆栈
实施效果
表格
| 指标 | 未使用 logging | 使用企业级 logging | 提升 |
|---|---|---|---|
| 排查效率 | 极低,靠猜 | 定位行号、堆栈、时间 | 极显著 |
| 日志混乱 | 严重,多模块冲突 | 统一格式、统一输出 | 清晰 |
| 磁盘风险 | 无限增长 | 自动切割清理 | 安全 |
| 可观测性 | 无 | 支持采集系统 | 生产可用 |
6.2 失败教训
❌ 案例二:无规范日志导致线上故障无法排查问题某项目全程使用 print,上线后出现:
- 无时间、无级别、无堆栈
- 无法定位异常位置
- 无法复现问题
- 无法定位是哪台机器、哪个请求出错
经验教训⚠️ 警示:
- 企业项目严禁使用 print
- 必须统一日志格式与输出
- 必须记录异常堆栈
- 必须持久化并切割
七、常见问题解答
7.1 技术问题
Q1:日志重复输出?💡 原因:logger 被多次实例化,重复添加 Handler。解决:判断 if logger.handlers 再添加。
Q2:中文乱码?解决:encoding='utf-8'。
Q3:生产环境不想输出 DEBUG?解决:
python
运行
console_handler.setLevel(logging.INFO)
Q4:如何记录完整异常堆栈?解决:使用 logger.exception(e),自动捕获堆栈。
7.2 应用问题
Q5:多模块如何共用同一个 logger?在 utils/logger.py 中创建 logger,其他文件 import 即可。
Q6:日志太多如何优化?
- 提升生产环境级别为 INFO
- 按时间 / 大小自动切割
- 定期清理旧日志
- 使用消息队列异步输出
八、未来发展趋势
8.1 技术趋势
表格
| 趋势 | 描述 | 时间 |
|---|---|---|
| 结构化日志 | JSON 格式,便于采集 | 已普及 |
| 异步日志 | 不阻塞业务 | 1–2 年 |
| 云原生日志 | 直接对接云监控 | 进行中 |
| AI 日志分析 | 自动异常检测 | 2–3 年 |
8.2 应用趋势
- 日志 → 监控 → 告警 → 自愈一体化
- 微服务统一日志链路追踪
- 大模型自动分析日志故障原因
8.3 职业发展
表格
| 阶段 | 学习重点 | 时间 |
|---|---|---|
| 入门 | 基础配置、级别输出 | 1 天 |
| 进阶 | 多 Handler、切割、封装 | 3 天 |
| 专业 | 结构化、异步、多环境 | 1 周 |
| 专家 | 日志平台、链路追踪、告警 | 1 月 + |
九、本章小结
9.1 核心要点回顾
✅ 本章核心内容:① 概念理解:logging 级别、组件、架构② 技术原理:Logger/Handler/Formatter 协同工作③ 基础使用:basicConfig 快速上手④ 高级用法:切割、多输出、单例、异常捕获⑤ 企业封装:可直接上线的通用日志工具⑥ 最佳实践:规范、禁忌、避坑指南
9.2 学习建议
💡 给读者的建议:① 所有项目从第一天就用 logging,禁止 print② 直接复制本章企业封装代码使用③ 统一团队日志规范④ 生产环境必须按天 / 按大小切割
十、课后练习
练习一:基础使用用 basicConfig 配置日志,输出到控制台和文件,并区分级别。
练习二:高级封装基于本章代码,实现一个支持:
- 控制台 + 文件双输出
- 按天切割
- 中文不乱码
- 全局单例的日志工具,并在多模块中调用。
练习三:实战落地在你的项目中替换所有 print 为 logging,并验证输出正常。
十一、参考资料
📄 官方文档:
- Python logging 官方:https://docs.python.org/3/library/logging.html
- logging.handlers:https://docs.python.org/3/library/logging.handlers.html
&spm=1001.2101.3001.5002&articleId=160348234&d=1&t=3&u=75629047ef6b4b5faa9e125d975b5c94)
297

被折叠的 条评论
为什么被折叠?



