load_dotenv()必须在os.getenv()调用前执行,否则返回None;默认只读当前工作目录的.env文件,路径错、编码BOM、大小写不一致、变量优先级(系统变量高于.env)等均会导致失效。

load_dotenv() 必须在任何读取环境变量的代码之前调用,否则 os.getenv() 拿不到值——这是最常踩的坑。
为什么 load_dotenv() 没生效?
常见现象:明明写了 load_dotenv(),但 os.getenv("API_KEY") 还是返回 None。
- 调用位置错了:它必须出现在所有依赖环境变量的代码之前,比如不能写在 Flask
app = Flask(__name__)之后、也不能放在函数内部再调用 - .env 文件不在默认路径:
load_dotenv()默认只找当前工作目录(os.getcwd())下的.env,不是项目根目录;运行脚本时如果从其他路径执行(如python src/main.py),当前目录就变成src/,自然找不到 - 文件编码或 BOM 问题:Windows 编辑器保存的 UTF-8 with BOM 会导致解析失败,建议用 VS Code 或 Notepad++ 保存为纯 UTF-8
- 变量名大小写不一致:
os.getenv("api_key")拿不到API_KEY=xxx,环境变量名严格区分大小写
load_dotenv() 的关键参数怎么选?
默认行为不够用时,这几个参数最常改:
-
dotenv_path=".env.development":指定非默认文件名,适合多环境切换 -
override=False(默认值):不覆盖已存在的系统环境变量;设为True才能强行用 .env 覆盖(比如本地调试想临时覆盖 CI 注入的生产密钥) -
verbose=True:加载时打印日志,能立刻看到是否找到文件、加载了哪些变量,调试必备 -
encoding="utf-8":显式指定编码,避免中文或特殊字符乱码
如何安全地读取并转换类型?
环境变量永远是字符串,直接当布尔值或整数用会出错:
- 别写
if os.getenv("DEBUG"): ...——"False"字符串也是真值,应该用os.getenv("DEBUG", "False").lower() == "true" - 整数要
int(os.getenv("PORT", "8000")),但记得加 try/except,避免ValueError - 推荐用
ast.literal_eval()解析布尔、列表、None:ast.literal_eval(os.getenv("ENABLE_FEATURES", "False")) - 敏感变量缺失时主动报错,而不是静默失败:
if not os.getenv("DATABASE_URL"): raise RuntimeError("Missing DATABASE_URL")
生产环境还能用 .env 文件吗?
不能直接用——.env 文件本身不该出现在生产服务器上。
- CI/CD 流程中,应通过 secret 管理工具(如 GitHub Actions secrets、GitLab CI variables)注入变量,而不是上传 .env 文件
- Docker 部署时,用
docker run -e DATABASE_URL=...或--env-file传入,而非 COPY .env 到镜像里 - 如果你发现
load_dotenv()在生产环境也执行成功了,说明配置没隔离好,存在泄露风险 - 开发时用
.env+.gitignore,生产时靠基础设施注入,这才是分层清晰的做法
真正容易被忽略的是变量优先级:系统环境变量永远高于 .env 文件里的同名变量。这意味着你本地 export DEBUG=true 后再跑程序,.env 里的 DEBUG=False 就完全无效——这个行为在调试和部署时经常造成预期外的结果。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











