【每日一技】Pydantic配置管理最佳实践(二)

0 阅读2分钟

📅 今日知识点

  • 核心主题上一篇文章我们讲解了如何使用pydantic做配置管理,本期文章展示在使用Pydantic管理应用配置时,如何进行多环境配置切换

  • 适用场景:应用的多环境部署

  • 一句话总结:通过Pydantic实现环境隔离的配置管理,一套代码适配多种部署环境

🧩 核心原理(简化版)

  • 基于环境变量动态选择配置类,实现配置的环境隔离

  • 核心逻辑:通过工厂函数,根据ENVIRONMENT环境变量返回对应的配置实例

  • 核心价值:避免硬编码环境判断,支持配置热重载,提升部署灵活性

1. 多环境配置类

import os
from enum import Enum
from typing import Union
from pydantic import field_validator
from pydantic_settings import BaseSettings

class Environment(str, Enum):
    """环境枚举"""
    DEVELOPMENT = "dev"
    STAGING = "staging"
    PRODUCTION = "prod"

class EnvSettings(BaseSettings):
    """环境相关配置"""
    environment: Environment = Environment.DEVELOPMENT
    secret_key: str = ""  # 提供默认空值,避免必填验证错误

    @field_validator('environment', mode="before")
    @classmethod
    def validate_environment(cls, v):
        if isinstance(v, str):
            return Environment(v.lower())
        return v

class DevSettings(EnvSettings):
    def __init__(self, _env_file: str = ".env.prod"):
        super().__init__()
        self.__env_file = _env_file

    """开发环境配置"""
    debug: bool = True
    log_level: str = "DEBUG"

    model_config = {
        "env_file": ".env.dev",
        "env_file_encoding": "utf-8",
        "case_sensitive": False,
        "extra": "ignore"
    }

class ProdSettings(EnvSettings):
    def __init__(self, _env_file: str = ".env.prod"):
        super().__init__()
        self.__env_file = _env_file

    """生产环境配置"""
    debug: bool = False
    log_level: str = "WARNING"

    model_config = {
        "env_file": ".env.prod",
        "env_file_encoding": "utf-8",
        "case_sensitive": False,
        "extra": "ignore"
    }

2. 环境配置的工场函数

# 环境工厂函数
def get_settings() -> Union[DevSettings, ProdSettings]:
    """根据环境变量返回对应配置"""
    env = os.getenv("ENVIRONMENT", "dev").lower()
    if env == "prod":
        return ProdSettings(_env_file=".env.prod")
    else:
        return DevSettings(_env_file=".env.dev")

3. 测试

if __name__ == "__main__":
    settings = get_settings()
    print(f"当前环境: {settings.environment}")
    print(f"调试模式: {settings.debug}")
    print(f"Secret Key: {settings.secret_key}")

测试结果:

当前环境: Environment.PRODUCTION
调试模式: False
Secret Key: 78910

4. 核心要点

# 1. 环境枚举:使用Enum确保环境值的有效性
class Environment(str, Enum):
    """环境枚举"""
    DEVELOPMENT = "dev"
    STAGING = "staging"
    PRODUCTION = "prod"

  


# 2. 配置继承:不同环境配置继承基础配置
class DevSettings(BaseSettings):
    debug: bool = True

  


# 3. 工厂模式:根据环境变量返回配置实例
def get_settings() -> Union[DevSettings, ProdSettings]:
    """根据环境变量返回对应配置"""
    env = os.getenv("ENVIRONMENT", "dev").lower()
  
    if env == "prod":
        return ProdSettings(_env_file=".env.prod")
    else:
        return DevSettings(_env_file=".env.dev")

⚠️ 避坑指南(简洁重点)

核心坑:环境变量未设置导致的默认行为

# ❌ 问题:未设置ENVIRONMENT时总是返回开发配置
env = os.getenv("ENVIRONMENT", "dev")  # 默认值可能导致生产环境误用开发配置

# ✅ 最佳实践:生产环境必须显式设置
env = os.environ["ENVIRONMENT"]

✅ 今日总结

  • 多环境配置管理核心是:环境隔离和通过工厂函数实现配置的灵活管理
  • 关键要点:环境枚举、配置继承、环境文件分离、工厂模式、环境变量优先