You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI 同一 Settings 类中加载多套环境配置的实现咨询

FastAPI + Pydantic 多环境动态加载.env配置方案

核心思路

先从优先级高于.env文件的来源(系统环境变量、服务启动参数、容器环境配置等)获取当前运行的环境标识,再根据标识拼接对应.env文件的路径,最后通过自定义配置源加载目标文件的配置,避免循环依赖问题。

Pydantic V2 实现代码

from pydantic_settings import BaseSettings, DotEnvSettingsSource
from functools import lru_cache
from typing import Tuple, Callable

class APISettings(BaseSettings):
    # 环境标识,必须从系统环境变量/启动参数传入
    environment: str
    # 业务配置字段
    port: int = 8000
    db_url: str
    debug: bool = False

    @classmethod
    def settings_customise_sources(
        cls,
        settings_cls: type[BaseSettings],
        init_settings: Callable,
        env_settings: Callable,
        dotenv_settings: Callable,
        file_secret_settings: Callable,
    ) -> Tuple[Callable, ...]:
        # 第一步:优先从初始化参数、系统环境变量读取环境标识
        temp_config = init_settings(settings_cls) or env_settings(settings_cls)
        current_env = temp_config.get("environment")
        if not current_env or current_env not in ["dev", "stage", "prod"]:
            raise ValueError("请传入合法的环境标识:dev/stage/prod")
        
        # 第二步:拼接对应环境的配置文件路径
        env_file_path = f"core/configs/.env.{current_env}"

        # 第三步:构造自定义的dotenv配置源
        custom_dotenv = DotEnvSettingsSource(
            settings_cls,
            env_file=env_file_path,
            env_file_encoding="utf-8"
        )

        # 配置源优先级:初始化参数 > 系统环境变量 > 自定义.env文件 > 机密文件
        return (init_settings, env_settings, custom_dotenv, file_secret_settings)

# 配置单例缓存
@lru_cache()
def get_api_settings() -> APISettings:
    return APISettings()

Pydantic V1 实现代码

from pydantic import BaseSettings
from pydantic.env_settings import SettingsSourceCallable
from functools import lru_cache
from typing import Tuple, Dict, Any
from dotenv import dotenv_values

class APISettings(BaseSettings):
    environment: str
    port: int = 8000
    db_url: str
    debug: bool = False

    class Config:
        @classmethod
        def customise_sources(
            cls,
            init_settings: SettingsSourceCallable,
            env_settings: SettingsSourceCallable,
            file_secret_settings: SettingsSourceCallable,
        ) -> Tuple[SettingsSourceCallable, ...]:
            # 自定义配置源加载函数
            def load_target_env_config(settings: BaseSettings) -> Dict[str, Any]:
                # 读取环境标识
                current_env = init_settings(settings).get("environment") or env_settings(settings).get("environment")
                if not current_env or current_env not in ["dev", "stage", "prod"]:
                    raise ValueError("请传入合法的环境标识:dev/stage/prod")
                # 加载对应.env文件
                return dotenv_values(f"core/configs/.env.{current_env}", encoding="utf-8")
            
            # 调整配置加载优先级
            return (init_settings, env_settings, load_target_env_config, file_secret_settings)

@lru_cache()
def get_api_settings() -> APISettings:
    return APISettings()

使用方法

启动服务时传入对应环境标识即可:

  • Linux/Mac 命令:ENVIRONMENT=prod uvicorn main:app --host 0.0.0.0
  • Windows 命令:set ENVIRONMENT=dev && uvicorn main:app --host 0.0.0.0
  • Docker 启动:docker run -e ENVIRONMENT=stage your-image-name

注意事项

environment字段必须从系统环境变量等高于.env的优先级来源传入,不可从目标.env文件读取,否则会出现循环依赖问题

  • 本地开发如果不想每次手动传环境变量,可以在项目根目录新增一个不提交到代码库的.env文件,仅写入environment=dev,在自定义配置源中增加该文件的加载逻辑即可
  • 可以额外增加配置文件存在性校验,避免环境标识传错导致找不到配置文件的问题

内容的提问来源于stack exchange,提问作者mrgrj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 05:06:03