Appearance
48|配置管理与多环境
代码中硬编码配置(数据库地址、密钥、超时时间)会带来几个问题:不同环境需要不同值、敏感信息不能进版本控制、修改配置需要重新部署。把配置从代码中分离出来,通过环境变量或配置文件管理,是工程化的基本要求。
一、环境变量
python
import os
DB_URL = os.getenv("DATABASE_URL", "sqlite:///ops.db")
SECRET_KEY = os.environ["SECRET_KEY"] # 必填,没有就报错
DEBUG = os.getenv("DEBUG", "false").lower() == "true"| 方法 | 行为 | 用途 |
|---|---|---|
os.getenv(key) | 不存在返回 None | 可选配置 |
os.getenv(key, default) | 不存在返回默认值 | 有默认值的配置 |
os.environ[key] | 不存在抛 KeyError | 必填配置 |
.env 文件
开发时把环境变量写在 .env 文件中,不用每次都 export:
bash
# .env
DATABASE_URL=sqlite:///ops.db
SECRET_KEY=dev-secret-key
DEBUG=truebash
# 加载 .env
uv add python-dotenvpython
from dotenv import load_dotenv
load_dotenv() # 从 .env 文件加载环境变量.env 文件不能提交到版本控制,在 .gitignore 中排除:
gitignore
.env
.env.local
.env.production二、pydantic-settings
用 Pydantic 模型管理配置,自动从环境变量读取、类型转换、校验:
bash
uv add pydantic-settingspython
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str = "sqlite:///ops.db"
secret_key: str
debug: bool = False
access_token_expire_minutes: int = 30
class Config:
env_file = ".env"
settings = Settings()| 特性 | 行为 |
|---|---|
| 自动映射 | database_url 对应环境变量 DATABASE_URL |
| 类型转换 | 环境变量都是字符串,自动转成模型声明的类型 |
| 必填校验 | secret_key 没有默认值且环境变量中没有时,启动报错 |
.env 支持 | Config.env_file 指定文件 |
使用:
python
from config import settings
print(settings.database_url)
print(settings.debug)三、多环境配置
环境变量区分
bash
# 启动时指定环境
ENV=production uv run uvicorn main:apppython
class Settings(BaseSettings):
env: str = "development"
database_url: str
debug: bool = False
class Config:
env_file = ".env"
settings = Settings()
# 根据环境调整默认值
if settings.env == "development":
settings.debug = True多文件配置
python
class Config:
env_file = f".env.{os.getenv('ENV', 'development')}"bash
.env.development
.env.staging
.env.production四、敏感信息管理
密钥生成
python
import secrets
# 生成安全的随机密钥
secret = secrets.token_urlsafe(32)
print(secret)生产环境密钥来源
| 方式 | 适用场景 |
|---|---|
| 环境变量 | Docker、systemd、云服务 |
| 密钥管理服务 | AWS Secrets Manager、阿里云 KMS |
| 配置文件(加密) | Ansible Vault、sops |
不要把密钥写在代码里或提交到 Git。
五、常见错误
配置和代码混在一起
python
# 错误
DB_URL = "sqlite:///ops.db" # 硬编码
# 正确
DB_URL = os.getenv("DATABASE_URL", "sqlite:///ops.db").env 提交到版本控制
bash
# 错误:.env 进了 Git,密钥泄露
git add .env
git commit -m "add config"
# 正确
# .gitignore 中加入 .env没有给必填配置报错
python
# 错误:运行时才发现配置缺失
database_url = os.getenv("DATABASE_URL") # None
connect(database_url) # 报错
# 正确:启动时就检查
class Settings(BaseSettings):
database_url: str # 没有默认值,启动时缺失会报错