[环境管理/Python] dotenv : Python 轻量级环境变量管理库
1 概述: dotenv
dotenv是一个轻量级且必备的工具,用于【管理环境变量】,特别适合初级开发者学习配置管理。
1.1 为什么要用 dotenv?
| 场景 | 问题 | dotenv 解决方案 |
|---|---|---|
| 代码中硬编码密钥 | 泄露风险、难以维护 | 分离到 .env 文件 |
| 不同环境配置不同 | 改代码麻烦 | 一套代码,多套配置 |
| 团队协作 | 每个人配置不同 | .env 本地管理,.env.example 共享模板 |
- 加载一次,随处读取,文件保密,集中管理,生产脱钩。
1.2 安装与基础用法
安装
pip install python-dotenv
最简示例
.env文件
放在项目根目录,不要提交到 Git:
# 数据库配置
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
DEBUG=True
API_KEY=sk-1234567890abcdef
- Python 代码:
from dotenv import load_dotenv
import os
# 加载 .env 文件到环境变量
load_dotenv()
# 像读取普通环境变量一样使用
db_url = os.getenv("DATABASE_URL")
debug_mode = os.getenv("DEBUG", "False") == "True" # 带默认值
api_key = os.getenv("API_KEY")
print(f"数据库: {db_url}")
print(f"调试模式: {debug_mode}")
1.3 核心 API 详解
load_dotenv() —— 最常用的加载方式
from dotenv import load_dotenv
# 默认行为:从当前工作目录向上查找 .env 文件
load_dotenv()
# 指定具体路径
load_dotenv(dotenv_path="/path/to/.env")
# 自定义 .env 文件名
load_dotenv(dotenv_path=".env.local")
# 不覆盖已存在的环境变量(安全模式)
load_dotenv(override=False) # 默认 True,会覆盖系统环境变量
find_dotenv() —— 自动查找文件
from dotenv import load_dotenv, find_dotenv
# 自动向上级目录查找 .env
env_path = find_dotenv(raise_error_if_not_found=True)
load_dotenv(env_path)
set_key() / get_key() —— 读写 .env 文件
from dotenv import set_key, get_key
# 读取特定键
value = get_key(".env", "DATABASE_URL")
# 修改或新增键值(会修改文件!)
set_key(".env", "NEW_VAR", "new_value")
1.4 最佳实践(初级工程师必看)
✅ 正确的项目结构
my_project/
├── .env # ← 本地配置文件(gitignore)
├── .env.example # ← 模板文件(提交到git)
├── .gitignore
├── src/
│ └── config.py # ← 集中管理配置读取
└── main.py
✅ .gitignore 配置
# 忽略所有 .env 文件,但保留模板
.env
.env.local
.env.*.local
!.env.example
✅ .env.example 模板(给团队看)
# 复制此文件为 .env 并填写真实值
DATABASE_URL=postgresql://user:pass@localhost/dbname
DEBUG=False
API_KEY=your_api_key_here
SECRET_KEY=generate_a_random_string
✅ 集中配置管理(推荐模式)
config.py:
from dotenv import load_dotenv
from dataclasses import dataclass
import os
load_dotenv()
@dataclass(frozen=True)
class Config:
"""应用配置,只读"""
DATABASE_URL: str = os.getenv("DATABASE_URL", "")
DEBUG: bool = os.getenv("DEBUG", "False").lower() == "true"
API_KEY: str = os.getenv("API_KEY", "")
PORT: int = int(os.getenv("PORT", "8000"))
# 全局配置实例
config = Config()
# 使用方式
# from config import config
# print(config.DATABASE_URL)
1.5 常见坑与解决方案
| 坑 | 原因 | 解决 |
|---|---|---|
修改 .env 后代码没变化 |
只在导入时加载一次 | 重启程序或手动重新 load_dotenv() |
| 布尔值判断错误 | os.getenv 返回字符串 |
"True" == "true" 或 str.lower() |
| 多行值解析失败 | 值包含换行符 | 用引号包裹:MY_VAR="line1\nline2" |
值包含 # 被截断 |
# 被当注释 |
用引号包裹:URL="http://a.com#fragment" |
| 生产环境变量不生效 | 优先级问题 | 生产环境直接用系统环境变量,不依赖 .env |
1.6 快速参考卡片
from dotenv import load_dotenv, find_dotenv
import os
# 标准启动代码
load_dotenv(find_dotenv())
# 读取(带默认值)
value = os.getenv("KEY", "default")
# 类型转换
port = int(os.getenv("PORT", "8080"))
debug = os.getenv("DEBUG", "").lower() in ("true", "1", "yes")
# 检查必填项
required = ["DATABASE_URL", "API_KEY"]
missing = [k for k in required if not os.getenv(k)]
if missing:
raise ValueError(f"缺少环境变量: {missing}")
1.X 总结
| 要点 | 说明 |
|---|---|
| 核心功能 | 把配置从代码分离到 .env 文件 |
| 安全原则 | .env 永不提交 Git,用 .env.example 模板 |
| 架构模式 | 用 config.py 集中管理,避免到处 os.getenv |
| 生产部署 | 云平台直接设置环境变量,不依赖 .env 文件 |
- 掌握 dotenv 是写出专业、可维护、安全 Python 代码的第一步
Z FAQ for dotenv
Q:是否支持环境变量的引用?
- 支持。
python-dotenv支持在.env文件中使用${VAR}或$VAR语法引用其他环境变量。
用法示例
- .env 文件:
# 基础变量
BASE_PATH=/home/user/project
# 引用语法
DATA_DIR=${BASE_PATH}/data
LOG_DIR=$BASE_PATH/logs # 简写形式也可
# 嵌套引用 + 默认值(需启用 interpolate)
FULL_URL=${PROTOCOL:-https}://${HOST:-localhost}:${PORT:-8080}
- Python 代码:
from dotenv import load_dotenv
import os
# 关键:启用 interpolate=True(默认已开启)
load_dotenv(interpolate=True)
print(os.getenv("DATA_DIR")) # /home/user/project/data
print(os.getenv("LOG_DIR")) # /home/user/project/logs
print(os.getenv("FULL_URL")) # https://localhost:8080
关键特性速查
- 语法 :
${VAR}|$VAR|${VAR:-default}|${VAR:?error} - 说明 : 标准引用 | 简写引用(仅限简单场景) | 默认值 | 缺失报错
- 示例 :
${BASE}/subdir|$BASE/subdir|${PORT:-3000}|${SECRET:?required}
注意事项
# 禁用插值(纯文本模式)
load_dotenv(interpolate=False) # 原样保留 ${XXX} 字符串
# 循环引用会报错
# A=$B 且 B=$A → dotenv.main.DotEnvInterpolationError
# 系统环境变量优先级高于 .env 内定义
# 若 export BASE_PATH=/system,则 .env 中 BASE_PATH 被覆盖
实际应用
# .env
PROJECT_NAME=myapp
VERSION=1.0.0
IMAGE_TAG=${PROJECT_NAME}:${VERSION} # myapp:1.0.0
COMPOSE_PROJECT_NAME=${PROJECT_NAME}_dev # myapp_dev
- 总结:
${}语法原生支持,适合构建路径、标签等组合值,但避免循环依赖。
Y 推荐文献
X 参考文献
本文作者:
千千寰宇
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

浙公网安备 33010602011771号