在Python开发中,环境变量管理是保证项目安全性和可移植性的关键环节。通过将敏感信息(API密钥、数据库凭证等)与代码分离,开发者可以:
该库通过.env
文件实现环境变量的自动化管理,主要特性包括:
.env
文件.env.dev
, .env.prod
等)PATH=${ROOT}/bin
)# 安装最新版本
pip install python-dotenv
# 创建.env文件
echo "DEBUG=True\nDB_HOST=localhost" > .env
from dotenv import load_dotenv
import os
# 加载.env文件
load_dotenv()
# 访问环境变量
print(os.getenv('DEBUG')) # 输出: True
print(os.getenv('DB_HOST')) # 输出: localhost
# 根据环境加载不同配置文件
env = os.getenv('ENV', 'dev')
load_dotenv(f'.env.{env}')
# 生产环境加载.env.prod
# 开发环境加载.env.dev
# .env文件内容
ROOT_PATH=/var/www
LOG_DIR=${ROOT_PATH}/logs
CACHE_DIR=${ROOT_PATH}/cache
# 获取布尔值
DEBUG = os.getenv('DEBUG', False)
if isinstance(DEBUG, str):
DEBUG = DEBUG.lower() in ('true', '1', 't')
# 自动转换版
from dotenv import dotenv_values
config = dotenv_values()
DEBUG = config.get('DEBUG', False) # 自动转为bool
from dotenv import dotenv_values
class Config:
def __init__(self):
self.config = {
**dotenv_values(".env.base"), # 基础配置
**dotenv_values(".env.secret"), # 密钥配置
**os.environ # 系统环境变量
}
def get(self, key):
return self.config.get(key)
# 忽略.env文件提交
echo ".env*" >> .gitignore
echo "!.env.example" >> .gitignore
# 创建配置模板
cp .env .env.example
sed -i 's/=.*/=/' .env.example
project-root/
├── .env.dev # 开发环境
├── .env.staging # 预发布环境
├── .env.prod # 生产环境
└── docker-compose.yml
FROM python:3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# 加载环境变量
COPY .env.prod .env
COPY . .
CMD ["python", "main.py"]
# 结合Consul/Vault的动态配置
load_dotenv() # 加载基础配置
# 从配置中心获取动态配置
config = get_remote_config(os.getenv('CONFIG_ENDPOINT'))
os.environ.update(config)
from cryptography.fernet import Fernet
# 加密.env文件
key = Fernet.generate_key()
cipher_suite = Fernet(key)
encrypted_env = cipher_suite.encrypt(open('.env').read().encode())
with open('.env.enc', 'wb') as f:
f.write(encrypted_env)
# 运行时解密
load_dotenv(stream=cipher_suite.decrypt(open('.env.enc').read()))
加载顺序:
1. 系统环境变量
2. .env.local
3. .env.${ENV}
4. .env
问题现象 | 解决方案 |
---|---|
变量值为None | 检查.env文件编码应为UTF-8 |
特殊字符解析失败 | 使用双引号包裹值:PASS=“abc#123” |
多环境配置冲突 | 明确指定加载路径:load_dotenv(‘.env.prod’) |
Docker环境变量覆盖 | 在docker-compose中声明volumes |
# 延迟加载示例
class LazyEnv:
def __init__(self):
self._loaded = False
self._config = {}
def __getattr__(self, name):
if not self._loaded:
self._config = dotenv_values()
self._loaded = True
return self._config.get(name)
django-dotenv
flask-dotenv
%load_ext dotenv
dotenv run -- python app.py