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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:52:42