Python 项目如何管理环境变量和配置?为什么不应该把密钥写进代码?
简化版
Python 项目应把配置和代码分离,数据库密码、API Key、SECRET_KEY 等敏感信息通过环境变量、配置中心或密钥管理系统注入。.env 可以用于本地开发,但不要把真实密钥提交到仓库;生产环境应使用平台提供的 secret 管理能力。
详细版
常见做法是代码读取环境变量:
import os
DATABASE_URL = os.environ["DATABASE_URL"]
DEBUG = os.getenv("DEBUG", "false").lower() == "true"
本地可用 .env 文件配合 python-dotenv,仓库只提交 .env.example。面试重点是:配置会随环境变化,密钥有泄露风险,配置加载要有默认值、校验和清晰优先级。
完整版教学
一、为什么配置要和代码分离
同一份代码要部署到开发、测试、预发、生产,不同环境的数据库、Redis、日志级别、第三方 Key 都不同。把配置写死会导致改环境就改代码。
代码: 同一份
配置: 随环境变化
配置外置后,镜像或包可以复用,环境差异由部署系统注入。
二、哪些属于敏感配置
数据库密码、JWT 密钥、Flask/Django SECRET_KEY、云厂商 AK/SK、支付密钥、Webhook secret 都属于敏感信息。泄露后可能导致数据和资金风险。
不能提交: real password/token/private key
可以提交: .env.example
仓库历史很难彻底清理,密钥一旦提交就应视为泄露并轮换。
三、环境变量怎么读
os.environ["KEY"] 缺失会抛 KeyError,适合必填配置;os.getenv("KEY", default) 适合有默认值的配置。
SECRET_KEY = os.environ["SECRET_KEY"]
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
必填配置启动时失败,比运行中某个请求才失败更好。
配置错误要尽早失败,密钥缺失不要静默用默认弱值。
四、.env 文件适合什么
.env 适合本地开发,让开发者不必每次手动 export 环境变量。生产不应依赖手工 .env 文件,而应使用容器平台、CI/CD secret、KMS 或配置中心。
.env -> 本地真实值,不提交
.env.example -> 示例 key,不含秘密,提交
.gitignore 应忽略真实 .env。
五、配置优先级怎么设计
常见优先级是默认配置 < 配置文件 < 环境变量 < 启动参数。越靠后越具体。优先级混乱会让排查非常痛苦。
| 来源 | 优先级 |
|---|---|
| 默认值 | 低 |
| 配置文件 | 中 |
| 环境变量 | 高 |
| 命令行参数 | 最高 |
项目文档要写清楚最终读取顺序。
六、配置校验为什么重要
环境变量都是字符串,需要转换和校验。端口要转 int,DEBUG 要转 bool,URL 要校验格式。可以使用 Pydantic Settings、dynaconf、environs 等工具。
class Settings(BaseSettings):
database_url: str
debug: bool = False
配置校验能在启动阶段发现缺失和类型错误。
七、密钥泄露后的处理
密钥一旦进入 Git 历史、日志、截图或 CI 输出,就要按泄露处理。正确动作是立即吊销旧密钥、生成新密钥、更新部署环境,并排查访问日志。只把提交删掉通常不够,因为历史记录和远端缓存可能还在。
revoke -> rotate -> redeploy -> audit
面试中能说出“轮换”比只说“删除代码里的密钥”更完整。
八、配置加载的可观测性
生产排查时,经常需要知道当前应用读到了哪个环境、哪些非敏感配置生效。可以在启动日志中输出环境名、日志级别、功能开关,但不要输出密码、token、私钥。
safe log: ENV=prod LOG_LEVEL=INFO FEATURE_X=true
unsafe log: DATABASE_PASSWORD=...
配置要可排查,但密钥不能为了排查被打印出来。
九、常见误区与追问
- 误区:私有仓库提交密钥没关系。 私有仓库也可能泄露,成员和 CI 日志都有风险。
- 误区:生产可以用默认 SECRET_KEY。 默认弱密钥会导致签名伪造风险。
- 误区:环境变量都是安全的。 它们也可能被日志、进程信息或错误报告泄露,要谨慎。
- 追问:本地开发怎么配置?
.env+.env.example,真实.env不提交。 - 追问:密钥泄露怎么办? 立即撤销和轮换,清理使用方。
- 追问:bool 环境变量怎么读? 不能直接
bool("false"),要显式解析字符串。 - 追问:配置中心有什么价值? 集中管理、多环境、审计、动态更新。
十、加强记忆
配置管理记成“代码不变,配置随环境,秘密不进仓库”。必填配置启动即校验,本地用 .env,生产用 secret 管理,仓库只放 example。能讲清读取、优先级、校验和密钥轮换,才是工程化回答。