8.8 KiB
8.8 KiB
配置管理系统说明
概述
本项目采用分层配置管理系统,支持环境变量和配置文件两种方式,实现敏感信息与应用配置的分离。
配置文件结构
autool/
├── .env # 环境变量配置(敏感信息,不提交)
├── .env.example # 环境变量配置模板(提交到版本库)
├── config/
│ ├── current_env.txt # 当前环境标识(prod/test)
│ ├── prod.yaml # 生产环境配置
│ ├── test.yaml # 测试环境配置
│ ├── local.yaml # 本地覆盖配置(不提交)
│ └── local.yaml.example # 本地配置示例
├── config_loader.py # 配置文件加载模块
├── env_loader.py # 环境变量加载模块
└── config_usage_examples.py # 使用示例
配置优先级
配置加载的优先级从高到低为:
- 环境变量(
.env文件或系统环境变量) - 本地配置(
config/local.yaml或config/local.json) - 环境配置(
config/prod.yaml或config/test.yaml)
快速开始
1. 配置环境变量(敏感信息)
# 复制模板文件
cp .env.example .env
# 编辑 .env 文件,填入实际的 API 密钥
vim .env
.env 文件示例:
# AI 服务 API 密钥
GEMINI_API_KEY=your_actual_gemini_api_key_here
AZURE_API_KEY=your_actual_azure_api_key_here
QWEN_API_KEY=sk-your_actual_qwen_api_key_here
GLM_API_KEY=your_actual_glm_api_key_here
# 通知服务 Token
WECHAT_TOKEN_YFZ=your_actual_wechat_token_here
WECOM_TOKEN_TEAM1=your_actual_wecom_token_here
# 系统认证
IOS_PASSWORD=your_ios_device_password_here
2. 配置本地开发环境(可选)
如果需要覆盖环境配置(如修改路径、调试参数等),可创建本地配置文件:
# 复制本地配置模板
cp config/local.yaml.example config/local.yaml
# 编辑本地配置
vim config/local.yaml
config/local.yaml 示例:
# 本地开发配置覆盖
logging:
level: DEBUG # 覆盖生产环境的 INFO
output:
base_dir: D:/local_output # 使用本地路径
redis:
host: 127.0.0.1 # 使用本地 Redis
db: 9 # 独立的数据库编号
3. 在代码中使用配置
读取环境变量(推荐用于敏感信息)
from env_loader import get_env, get_env_bool, get_env_int
# 读取必需的环境变量
gemini_api_key = get_env(
"GEMINI_API_KEY",
required=True,
hint="See .env.example for setup instructions"
)
# 读取可选的环境变量(带默认值)
azure_api_key = get_env("AZURE_API_KEY", default="")
debug_mode = get_env_bool("DEBUG", default=False)
timeout = get_env_int("TIMEOUT", default=30)
读取配置文件(推荐用于应用配置)
from config_loader import load_config
# 加载配置(自动根据 current_env.txt 选择环境)
config = load_config()
# 读取配置项
output_dir = config.get("output", {}).get("base_dir", "./output")
log_level = config.get("logging", {}).get("level", "INFO")
redis_host = config.get("redis", {}).get("host", "localhost")
在配置文件中引用环境变量
配置文件支持 ${ENV_VAR_NAME} 格式引用环境变量:
config/prod.yaml:
notifications:
wechat:
yfz: "${WECHAT_TOKEN_YFZ}" # 从环境变量读取
wecom:
team1: "${WECOM_TOKEN_TEAM1}"
加载后会自动展开:
config = load_config()
token = config["notifications"]["wechat"]["yfz"] # 自动展开为实际的 token 值
最佳实践
1. 敏感信息 vs 应用配置
使用 .env 文件的场景:
- API 密钥、Token
- 数据库密码、Redis 密码
- 系统账户密码
- 其他不应出现在版本库中的敏感信息
使用配置文件(config/*.yaml)的场景:
- 应用功能开关
- 超时设置、重试次数等参数
- 文件路径、目录配置
- 日志级别、输出格式等
- 非敏感的业务配置
2. 环境隔离
# 切换到测试环境
echo "test" > config/current_env.txt
# 切换回生产环境
echo "prod" > config/current_env.txt
3. 本地开发配置
本地配置文件(config/local.yaml)用于覆盖环境配置,常见用途:
- 使用本地路径替代网络共享路径(提升速度)
- 启用详细日志(
DEBUG) - 连接本地数据库/Redis(避免影响生产环境)
- 临时关闭某些功能特性
4. 团队协作
提交到版本库的文件:
.env.example- 环境变量模板,不含真实密钥config/prod.yaml,config/test.yaml- 环境配置config/local.yaml.example- 本地配置示例
不提交到版本库的文件(已在 .gitignore 中):
.env- 包含真实密钥config/local.yaml,config/local.json- 个人本地配置
迁移指南
从硬编码配置迁移
旧代码:
# 硬编码在代码中
GEMINI_API_KEY = "AQ.Ab8RN6INSIgaGdgj5hmmYmi35QLw6K3likBz2bP37_I_F6V5aQ"
OUTPUT_DIR = "./output"
LOG_LEVEL = "INFO"
新代码:
from env_loader import get_env
from config_loader import load_config
# 敏感信息从环境变量读取
GEMINI_API_KEY = get_env("GEMINI_API_KEY", required=True)
# 应用配置从配置文件读取
config = load_config()
OUTPUT_DIR = config.get("output", {}).get("base_dir", "./output")
LOG_LEVEL = config.get("logging", {}).get("level", "INFO")
配置文件:
.env:
GEMINI_API_KEY=AQ.Ab8RN6INSIgaGdgj5hmmYmi35QLw6K3likBz2bP37_I_F6V5aQ
config/prod.yaml:
output:
base_dir: ./output
logging:
level: INFO
向后兼容处理
如果配置文件不存在,给出友好提示:
from config_loader import load_config
try:
config = load_config()
except FileNotFoundError as e:
print(f"Configuration file not found: {e}")
print("Please set up the configuration files in the config/ directory")
# 使用默认配置或退出
config = {} # 使用空配置或默认值
环境变量不存在时的友好提示:
from env_loader import get_env, print_env_setup_guide, check_required_env_vars
# 检查必需的环境变量
missing_vars = check_required_env_vars(["GEMINI_API_KEY", "AZURE_API_KEY"])
if missing_vars:
print(f"Missing required environment variables: {', '.join(missing_vars)}")
print_env_setup_guide()
raise ValueError("Please configure environment variables")
常见问题
Q1: .env 文件和 config/local.yaml 有什么区别?
.env用于敏感信息(API 密钥、密码等),格式固定为KEY=VALUEconfig/local.yaml用于本地配置覆盖(路径、参数等),支持嵌套结构
Q2: 如何验证配置是否生效?
from env_loader import get_env
from config_loader import load_config
# 检查环境变量
print(f"GEMINI_API_KEY: {get_env('GEMINI_API_KEY', default='<not set>')}")
# 检查配置文件
config = load_config()
print(f"Environment: {config.get('environment', {}).get('name', 'unknown')}")
print(f"Log level: {config.get('logging', {}).get('level', 'INFO')}")
Q3: 配置文件支持哪些格式?
- 环境变量:
.env文件(KEY=VALUE格式) - 配置文件:
.yaml、.yml、.json
推荐使用 YAML 格式,因为:
- 支持注释
- 支持嵌套结构
- 可读性更好
Q4: 如何在配置文件中引用环境变量?
使用 ${ENV_VAR_NAME} 格式:
notifications:
wechat:
yfz: "${WECHAT_TOKEN_YFZ}" # 引用环境变量
加载时会自动展开为环境变量的值。
Q5: 环境变量和配置文件冲突时如何处理?
环境变量的优先级最高。例如:
.env:
LOG_LEVEL=DEBUG
config/prod.yaml:
logging:
level: INFO
如果在配置文件中引用环境变量:
logging:
level: "${LOG_LEVEL}" # 实际值为 DEBUG(环境变量)
完整示例
参考 config_usage_examples.py 文件,包含:
- 环境变量读取示例
- 配置文件读取示例
- 完整的初始化函数
- 配置验证逻辑
- 迁移指南
安全建议
-
永远不要提交包含真实密钥的文件
.env已在.gitignore中排除- 提交前检查:
git status确保.env不在待提交列表中
-
定期轮换 API 密钥
- 定期更新
.env中的密钥 - 旧密钥在服务提供商处失效
- 定期更新
-
最小权限原则
- API 密钥只授予必需的权限
- 生产环境和开发环境使用不同的密钥
-
密钥泄露应急处理
- 立即在服务提供商处撤销泄露的密钥
- 生成新密钥并更新
.env文件 - 检查是否有未授权使用记录
参考资料
- 配置加载模块:
config_loader.py - 环境变量加载模块:
env_loader.py - 使用示例:
config_usage_examples.py - 环境变量模板:
.env.example - 本地配置示例:
config/local.yaml.example