应优先用 .env 管理运行时环境变量(如 database_url、secret_key),由 python-dotenv 在应用初始化前加载;pyproject.toml 仅用于工具链配置,不适用于运行时开关。

配置文件该用 .env 还是 pyproject.toml
项目启动时读不到 DEBUG=True,八成是配置加载顺序或格式错了。环境变量优先走 .env,但只对当前进程生效;pyproject.toml 更适合工具链配置(如 pytest、mypy),不是运行时配置的正经归宿。
实操建议:
立即学习“Python免费学习笔记(深入)”;
-
.env仅存敏感/可变值(DATABASE_URL、SECRET_KEY),用python-dotenv加载,且必须在应用初始化前调用load_dotenv() -
pyproject.toml别塞LOG_LEVEL = "DEBUG"这类运行时开关——它不被os.getenv()读取,框架也不会自动映射 - 如果用
settings.py模块管理配置,.env仅作覆盖层,别让它和硬编码值混在一起,否则改一个值要翻三处
os.getenv() 返回 None 但变量明明设了
常见于 Docker 容器里没把宿主机的 .env 文件挂进去,或 Python 进程启动方式绕过了 shell 环境(比如用 systemd 直接跑 python app.py)。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 检查是否真在进程内——打印
os.environ.get("PATH"),如果连/usr/bin都没有,说明环境彻底隔离了 - 不要依赖
export FOO=bar && python app.py,&&后的命令不一定继承前一个 export,改用子 shell:sh -c 'export FOO=bar; python app.py' - 用
os.getenv("FOO", "default")而非os.environ["FOO"],避免启动就崩;但别滥用默认值,掩盖配置缺失问题
多环境配置怎么分层才不爆炸
“开发/测试/生产”三套配置,最怕写成 config_dev.py、config_test.py、config_prod.py,然后靠 import 切换——一旦某处漏了 if DEBUG,线上就打日志到控制台。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 统一入口只有一个
Config类,用ENVIRONMENT环境变量决定行为,而不是 import 不同模块 - 基础配置写死在类里,差异化项全走
os.getenv(),比如SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL") or "sqlite:///dev.db" - 禁止在配置里写逻辑:不用
if ENVIRONMENT == "prod": LOG_LEVEL = "WARNING",改用外部传入,保持配置类纯数据性
Pydantic Settings 怎么用才不踩坑
用 BaseSettings 很爽,但升级到 Pydantic v2 后 env_file 默认不递归加载,.env.local 会被忽略;而且字段类型校验太强,int 字段遇到空字符串直接报错。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 显式指定
env_file=".env", env_file_encoding="utf-8",v2 不再默认找.env - 字段加
= None并配default_factory或用Optional[int],避免空值触发校验失败 - 别把
BaseSettings当万能胶——它不解决配置热更新、跨服务同步问题,只是帮你少写几行os.getenv()
docker build、pip install -e . 和 gunicorn 启动时,哪个环节漏了 --env-file 或忘了 load_dotenv(),问题就会藏得特别深。










