Pydantic自定义设置源优先级异常:Google Secret Manager提前加载问题
解决Pydantic中Google Secret Manager覆盖前置配置源的问题
问题根源
你遇到的问题是因为GoogleSecretManagerSettingsSource的默认实现未遵循Pydantic设置源的优先级规则——前置源已设置的字段,后置源不应覆盖。即便你把它放在源列表最后,若其逻辑是强制读取并覆盖所有字段,就会出现前置配置被覆盖的现象。
解决方案
方案一:按环境动态加载配置源(推荐)
贴合你“本地用环境变量+.env,GCP用环境变量+Secret Manager”的需求,通过环境变量判断是否加载Google Secret Manager源:
import os from pydantic_settings import BaseSettings, SettingsConfigDict, InitSettingsSource, EnvSettingsSource, DotEnvSettingsSource, PydanticBaseSettingsSource # 导入你的GoogleSecretManagerSettingsSource class Settings(BaseSettings): """Settings class.""" VAR1: str VAR2: str VAR3: str ENVIRONMENT: str = "local" # 默认本地环境 model_config = SettingsConfigDict(case_sensitive=True, extra="ignore", env_file=".env", env_file_encoding="utf-8") @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: InitSettingsSource, env_settings: EnvSettingsSource, dotenv_settings: DotEnvSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: # 基础配置源优先级:初始化参数 > 环境变量 > .env文件 sources = [init_settings, env_settings, dotenv_settings] # 仅在GCP环境下加入Secret Manager源,可通过ENVIRONMENT变量或GCP特有环境变量判断 if os.getenv("ENVIRONMENT") == "gcp" or os.getenv("GOOGLE_CLOUD_PROJECT") is not None: sources.append(GoogleSecretManagerSettingsSource(settings_cls)) return tuple(sources)
方案二:修改GoogleSecretManagerSettingsSource的逻辑
若需要在所有环境都加载Secret Manager但不覆盖前置配置,修改其get_field_value方法,仅当字段未被前置源设置时才从Secret Manager取值:
# 调整后的GoogleSecretManagerSettingsSource类 class GoogleSecretManagerSettingsSource(PydanticBaseSettingsSource): def __init__(self, settings_cls: type[BaseSettings]): self.settings_cls = settings_cls # 保留原有初始化逻辑 def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]: # 核心修改:仅字段未被前置源设置时,才读取Secret Manager if field.is_set: return None, field_name, False # 保留原有从Secret Manager获取值的逻辑 secret_value = self._fetch_secret_from_gcp(field_name) # 替换为实际取值方法 return secret_value, field_name, False # 保留其他原有方法
调整后,只有当前置源(初始化参数、环境变量、.env)未设置某个字段时,才会从Secret Manager读取对应值,不会覆盖已有的配置。
内容的提问来源于stack exchange,提问作者Adri1
相关产品推荐
相关产品推荐

