Python配置管理Skill python-configuration

这个技能涉及使用环境变量和类型化设置来管理Python应用程序的配置,支持外部化配置、pydantic-settings验证、秘密管理、环境特定行为实现。关键应用包括项目配置系统设置、迁移硬编码值、验证启动配置、确保代码跨环境可移植性,适用于后端开发、DevOps实践。

后端开发 0 次安装 0 次浏览 更新于 3/22/2026

名称: python-configuration 描述: 通过环境变量和类型化设置管理Python配置。适用于外部化配置、设置pydantic-settings、管理秘密或实现环境特定行为。

Python配置管理

通过环境变量和类型化设置将配置从代码中外部化。良好的配置管理使相同代码能在任何环境中运行而无需修改。

何时使用此技能

  • 设置新项目的配置系统
  • 从硬编码值迁移到环境变量
  • 实现pydantic-settings进行类型化配置
  • 管理秘密和敏感值
  • 创建环境特定设置(开发/预发布/生产)
  • 在应用程序启动时验证配置

核心概念

1. 外部化配置

所有环境特定值(URL、秘密、功能标志)来自环境变量,而非代码。

2. 类型化设置

在启动时解析和验证配置为类型化对象,而非分散在代码中。

3. 快速失败

在应用程序启动时验证所有必需配置。缺失配置应立即以清晰消息崩溃。

4. 合理默认值

为本地开发提供合理的默认值,同时对敏感设置要求显式值。

快速开始

from pydantic_settings import BaseSettings
from pydantic import Field

class Settings(BaseSettings):
    database_url: str = Field(alias="DATABASE_URL")
    api_key: str = Field(alias="API_KEY")
    debug: bool = Field(default=False, alias="DEBUG")

settings = Settings()  # 从环境变量加载

基础模式

模式1: 使用Pydantic的类型化设置

创建一个中央设置类来加载和验证所有配置。

from pydantic_settings import BaseSettings
from pydantic import Field, PostgresDsn, ValidationError
import sys

class Settings(BaseSettings):
    """从环境变量加载的应用程序配置。"""

    # 数据库
    db_host: str = Field(alias="DB_HOST")
    db_port: int = Field(default=5432, alias="DB_PORT")
    db_name: str = Field(alias="DB_NAME")
    db_user: str = Field(alias="DB_USER")
    db_password: str = Field(alias="DB_PASSWORD")

    # Redis
    redis_url: str = Field(default="redis://localhost:6379", alias="REDIS_URL")

    # API密钥
    api_secret_key: str = Field(alias="API_SECRET_KEY")

    # 功能标志
    enable_new_feature: bool = Field(default=False, alias="ENABLE_NEW_FEATURE")

    model_config = {
        "env_file": ".env",
        "env_file_encoding": "utf-8",
    }

# 在模块加载时创建单例实例
try:
    settings = Settings()
except ValidationError as e:
    print(f"配置错误:
{e}")
    sys.exit(1)

在整个应用程序中导入settings

from myapp.config import settings

def get_database_connection():
    return connect(
        host=settings.db_host,
        port=settings.db_port,
        database=settings.db_name,
    )

模式2: 对缺失配置快速失败

必需设置应在启动时立即以清晰错误崩溃。

from pydantic_settings import BaseSettings
from pydantic import Field, ValidationError
import sys

class Settings(BaseSettings):
    # 必需 - 无默认值表示必须设置
    api_key: str = Field(alias="API_KEY")
    database_url: str = Field(alias="DATABASE_URL")

    # 可选,带默认值
    log_level: str = Field(default="INFO", alias="LOG_LEVEL")

try:
    settings = Settings()
except ValidationError as e:
    print("=" * 60)
    print("配置错误")
    print("=" * 60)
    for error in e.errors():
        field = error["loc"][0]
        print(f"  - {field}: {error['msg']}")
    print("
请设置必需的环境变量。")
    sys.exit(1)

在启动时清晰的错误优于在请求中途的隐晦None失败。

模式3: 本地开发默认值

为本地开发提供合理的默认值,同时对秘密要求显式值。

class Settings(BaseSettings):
    # 有本地默认值,但生产环境会覆盖
    db_host: str = Field(default="localhost", alias="DB_HOST")
    db_port: int = Field(default=5432, alias="DB_PORT")

    # 总是必需 - 秘密无默认值
    db_password: str = Field(alias="DB_PASSWORD")
    api_secret_key: str = Field(alias="API_SECRET_KEY")

    # 开发便利
    debug: bool = Field(default=False, alias="DEBUG")

    model_config = {"env_file": ".env"}

为本地开发创建.env文件(永远不要提交):

# .env(添加到.gitignore)
DB_PASSWORD=local_dev_password
API_SECRET_KEY=dev-secret-key
DEBUG=true

模式4: 命名空间化的环境变量

为相关变量添加前缀以提高清晰度和调试便利。

# 数据库配置
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=admin
DB_PASSWORD=secret

# Redis配置
REDIS_URL=redis://localhost:6379
REDIS_MAX_CONNECTIONS=10

# 身份验证
AUTH_SECRET_KEY=your-secret-key
AUTH_TOKEN_EXPIRY_SECONDS=3600
AUTH_ALGORITHM=HS256

# 功能标志
FEATURE_NEW_CHECKOUT=true
FEATURE_BETA_UI=false

使env | grep DB_对调试有用。

高级模式

模式5: 类型强制转换

Pydantic自动处理常见转换。

from pydantic_settings import BaseSettings
from pydantic import Field, field_validator

class Settings(BaseSettings):
    # 自动将"true"、"1"、"yes"转换为True
    debug: bool = False

    # 自动将字符串转换为整数
    max_connections: int = 100

    # 解析逗号分隔字符串为列表
    allowed_hosts: list[str] = Field(default_factory=list)

    @field_validator("allowed_hosts", mode="before")
    @classmethod
    def parse_allowed_hosts(cls, v: str | list[str]) -> list[str]:
        if isinstance(v, str):
            return [host.strip() for host in v.split(",") if host.strip()]
        return v

用法:

ALLOWED_HOSTS=example.com,api.example.com,localhost
MAX_CONNECTIONS=50
DEBUG=true

模式6: 环境特定配置

使用环境枚举来切换行为。

from enum import Enum
from pydantic_settings import BaseSettings
from pydantic import Field, computed_field

class Environment(str, Enum):
    LOCAL = "local"
    STAGING = "staging"
    PRODUCTION = "production"

class Settings(BaseSettings):
    environment: Environment = Field(
        default=Environment.LOCAL,
        alias="ENVIRONMENT",
    )

    # 因环境而异的设置
    log_level: str = Field(default="DEBUG", alias="LOG_LEVEL")

    @computed_field
    @property
    def is_production(self) -> bool:
        return self.environment == Environment.PRODUCTION

    @computed_field
    @property
    def is_local(self) -> bool:
        return self.environment == Environment.LOCAL

# 用法
if settings.is_production:
    configure_production_logging()
else:
    configure_debug_logging()

模式7: 嵌套配置组

将相关设置组织到嵌套模型中。

from pydantic import BaseModel
from pydantic_settings import BaseSettings

class DatabaseSettings(BaseModel):
    host: str = "localhost"
    port: int = 5432
    name: str
    user: str
    password: str

class RedisSettings(BaseModel):
    url: str = "redis://localhost:6379"
    max_connections: int = 10

class Settings(BaseSettings):
    database: DatabaseSettings
    redis: RedisSettings
    debug: bool = False

    model_config = {
        "env_nested_delimiter": "__",
        "env_file": ".env",
    }

环境变量使用双下划线进行嵌套:

DATABASE__HOST=db.example.com
DATABASE__PORT=5432
DATABASE__NAME=myapp
DATABASE__USER=admin
DATABASE__PASSWORD=secret
REDIS__URL=redis://redis.example.com:6379

模式8: 从文件读取秘密

对于容器环境,从挂载文件读取秘密。

from pydantic_settings import BaseSettings
from pydantic import Field
from pathlib import Path

class Settings(BaseSettings):
    # 从环境变量或文件读取
    db_password: str = Field(alias="DB_PASSWORD")

    model_config = {
        "secrets_dir": "/run/secrets",  # Docker秘密位置
    }

如果环境变量未设置,Pydantic将查找/run/secrets/db_password

模式9: 配置验证

为复杂需求添加自定义验证。

from pydantic_settings import BaseSettings
from pydantic import Field, model_validator

class Settings(BaseSettings):
    db_host: str = Field(alias="DB_HOST")
    db_port: int = Field(alias="DB_PORT")
    read_replica_host: str | None = Field(default=None, alias="READ_REPLICA_HOST")
    read_replica_port: int = Field(default=5432, alias="READ_REPLICA_PORT")

    @model_validator(mode="after")
    def validate_replica_settings(self):
        if self.read_replica_host and self.read_replica_port == self.db_port:
            if self.read_replica_host == self.db_host:
                raise ValueError(
                    "读取副本不能与主数据库相同"
                )
        return self

最佳实践总结

  1. 永不硬编码配置 - 所有环境特定值来自环境变量
  2. 使用类型化设置 - Pydantic-settings进行验证
  3. 快速失败 - 在启动时对缺失必需配置崩溃
  4. 提供开发默认值 - 使本地开发容易
  5. 永不提交秘密 - 使用.gitignore的.env文件或秘密管理器
  6. 命名空间化变量 - DB_HOSTREDIS_URL提高清晰度
  7. 导入设置单例 - 不在代码各处调用os.getenv()
  8. 记录所有变量 - README应列出必需环境变量
  9. 早期验证 - 在启动时检查配置正确性
  10. 使用secrets_dir - 支持容器中的挂载秘密