autool/CONFIG_README.md
2026-06-17 19:44:18 +08:00

8.8 KiB
Raw Permalink Blame History

配置管理系统说明

概述

本项目采用分层配置管理系统,支持环境变量和配置文件两种方式,实现敏感信息与应用配置的分离。

配置文件结构

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 # 使用示例

配置优先级

配置加载的优先级从高到低为:

  1. 环境变量.env 文件或系统环境变量)
  2. 本地配置config/local.yamlconfig/local.json
  3. 环境配置config/prod.yamlconfig/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=VALUE
  • config/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 文件,包含:

  • 环境变量读取示例
  • 配置文件读取示例
  • 完整的初始化函数
  • 配置验证逻辑
  • 迁移指南

安全建议

  1. 永远不要提交包含真实密钥的文件

    • .env 已在 .gitignore 中排除
    • 提交前检查:git status 确保 .env 不在待提交列表中
  2. 定期轮换 API 密钥

    • 定期更新 .env 中的密钥
    • 旧密钥在服务提供商处失效
  3. 最小权限原则

    • API 密钥只授予必需的权限
    • 生产环境和开发环境使用不同的密钥
  4. 密钥泄露应急处理

    • 立即在服务提供商处撤销泄露的密钥
    • 生成新密钥并更新 .env 文件
    • 检查是否有未授权使用记录

参考资料

  • 配置加载模块:config_loader.py
  • 环境变量加载模块:env_loader.py
  • 使用示例:config_usage_examples.py
  • 环境变量模板:.env.example
  • 本地配置示例:config/local.yaml.example