进阶篇 · Advanced
lv.3 进阶
kp-037
日志与配置
1. 一句话定义
logging 是分层树形结构的分级日志系统(logger.info/warning/error),取代 print;配置遵循环境变量 > 配置文件 > 代码默认值的分层,秘密(密钥、密码)永远走环境变量。
2. 为什么重要
print 只能进 stdout 且无级别无结构,服务化后没法检索、没法分级关停;配置硬编码则是部署与安全的头号杀手。这两件小事决定程序"能不能进生产"。
3. 前置知识
4. 核心概念
python
import logging
logger = logging.getLogger(__name__) # 每模块一个 logger,以模块路径命名
logger.debug("详细调试 %s", var) # 惰性格式化:级别不够就不做字符串拼接
logger.info("请求完成", extra={"user_id": 42})
logger.warning("接近配额")
logger.error("失败", exc_info=True) # 附加 traceback- 级别:DEBUG < INFO < WARNING < ERROR < CRITICAL;根 logger 默认 WARNING。
- 树形传播:
pkg.mod的记录逐级上传到pkg与根,由根的 handler 决定输出——配置集中、使用分散。 - 配置一次成型:
python
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s %(message)s",
)5. 原理与机制
配置分层(12-Factor 原则):
python
import os
from dataclasses import dataclass
@dataclass(frozen=True)
class Config:
debug: bool = os.getenv("APP_DEBUG", "0") == "1"
db_url: str = os.environ["DATABASE_URL"] # 必填缺失即报错(fail fast)
api_key: str = os.environ["API_KEY"] # 秘密:只从环境来
# 可选叠加:.env 文件(python-dotenv)本地开发用;生产用真实环境变量结构化日志(JSON 行)在服务端场景逐步替代纯文本:python-json-logger 或自定义 Formatter——机器可检索、可聚合。
6. 关键事实(模型/图示)
text
logger.getLogger("myapp.api") ↓ 传播
logger.getLogger("myapp") ↓ 传播
root logger ──► handler(console/file/网络)──► formatter ──► 落地
异常处理黄金律:在"能处理"的层处理并 log;底层只 raise(kp-015)7. 直观类比
logging 是医院分诊台:debug 是"内部会诊记录"(默认不给外人看)、info 是"日常门诊"、error 是"急诊铃"——分诊台(root handler)决定哪些级别广播到哪块屏幕。配置分层像房间的可调灯光:装修时给默认亮度(代码默认值),每层楼有总开关(配置文件),住户手里的开关(环境变量)优先级最高。
8. 实例与案例
python
# 库的正确姿势:只用 getLogger + 不配置 handler(配置权交给应用)
# 应用的姿势:入口处 basicConfig / dictConfig 一次成型9. 常见误区
- 在生产用 print —— 无级别、无来源、无法关闭;统一切 logger。
- 每个文件都 basicConfig —— 它只对 root 生效且应只调一次;重复调用互相覆盖。
- 秘密进代码或配置文件提交 git —— 凭据只进环境变量/密管(Vault、云 KMS);
.env进.gitignore。 - f-string 拼进日志消息 ——
logger.debug(f"{heavy()}")无论级别都会先求值;用%s惰性占位。
10. 自测题
- 为什么推荐
logging.getLogger(__name__)? logger.debug(f"{x}")与logger.debug("%s", x)的性能差异根源?- 秘密配置的三条纪律?
参考答案
- logger 名即模块路径,自动接入层级树:传播、按模块开关级别、按包配置都成立。
- f-string 版在调用前就完成拼接(含 heavy() 求值);%s 版仅当级别放行才格式化。
- 不进代码、不进仓库(.gitignore + 历史扫描)、只经环境变量或密管注入。
11. 与其他知识点的关系
- kp-045 工程规范:日志规范与代码规范一起进 CI/评审。
- kp-016 文件 IO:FileHandler/RotatingFileHandler 的底层。
- kp-020 dataclass:Config 对象的现代写法。
12. 延伸阅读
- logging Cookbook(官方文档中最实用的章节)
- The Twelve-Factor App(Config 章节)