.env 文件仅用于本地开发,不得打包进 wheel 或 sdist,load_dotenv() 必须在入口文件顶部调用,显式指定路径,生产环境禁用,敏感变量需类型校验与缺失检查。

别打包 .env,也别硬编码;它只该在运行时加载,且永远不进 wheel 或 sdist。
load_dotenv() 必须在项目启动早期调用
python-dotenv 不会自动生效,load_dotenv() 是唯一触发点,且必须在任何依赖环境变量的代码执行前完成。常见错误是把它放在模块末尾、或仅在某个函数里调用——此时 os.getenv("DATABASE_URL") 可能返回 None,因为变量还没注入。
- 推荐位置:入口文件(如
main.py或app.py)最顶部,紧挨着 import 之后 - 不要在包内子模块里单独调用——容易重复加载或漏加载
- 如果使用异步框架(如 FastAPI),确保它在事件循环启动前执行
.env 文件路径和查找逻辑要明确
load_dotenv() 默认只查当前工作目录(os.getcwd())及其父级,直到找到第一个 .env。这看似方便,但容易出错:比如你在 tests/ 目录下运行 pytest,它可能加载了 tests/.env(如果存在),而不是项目根目录的。
- 显式指定路径更可靠:
load_dotenv(dotenv_path=".env")(相对路径基于当前文件) - 用
find_dotenv(usecwd=True)可强制从当前目录开始向上找,避免误匹配 - CI/CD 中建议统一设
CWD到项目根目录,再调用load_dotenv()
生产环境绝对不能依赖 .env 文件
容器或云平台(K8s、AWS ECS、Render)应通过原生方式注入环境变量,.env 只用于本地开发。如果误把 .env 打包进 wheel,不仅泄露敏感信息,还会污染部署环境——因为 load_dotenv() 在 site-packages 里找不到它,但用户可能误以为“有文件就安全”。
立即学习“Python免费学习笔记(深入)”;
-
pyproject.toml中禁止出现include = ["*.env"]或data-files = [".env"] - 验证是否打包:运行
python -m build后,用unzip -l mypkg-*.whl | grep env确认无结果 - 生产启动脚本中可加防护:
if os.getenv("ENVIRONMENT") == "production" and os.path.exists(".env"): raise RuntimeError("Refusing to load .env in production")
敏感值校验和类型转换不能靠 guess
os.getenv() 返回全是字符串,"False" 不等于 False,"123" 不是整数。硬写 int(os.getenv("PORT")) 会在缺失或格式错时直接抛 ValueError,而不是优雅 fallback。
- 用
ast.literal_eval()转布尔/数字/列表,比手动str.lower() == "true"更健壮 - 关键变量必须显式检查:
required = ["DATABASE_URL", "SECRET_KEY"]; missing = [k for k in required if not os.getenv(k)] - 更进一步,用
pydantic-settings做类型声明和验证,自动报错字段缺失或类型不符
真正难的不是加载 .env,而是让不同人、不同机器、不同环境都走同一套逻辑——路径、优先级、校验、打包边界,每一步漏掉一个,配置就变成定时炸弹。


















