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

使用pydantic-settings 2.4.0结合YAML配置文件时出现__fields_set__属性错误,求正确配置方案

使用pydantic-settings 2.4.0结合YAML配置文件时出现__fields_set__属性错误,求正确配置方案

兄弟,我来帮你搞定这个问题!你遇到的AttributeError: 'ServiceSettingsYaml' object has no attribute '__fields_set__',本质是因为你绕开了Pydantic BaseSettings的原生初始化逻辑,导致内部必要属性没被创建。下面给你分析原因+正确的配置方案:

问题根源

你继承了pydantic.v1.BaseSettings但重写了__init__方法,却没有调用父类的__init__()。Pydantic的BaseSettings在初始化时会自动创建__fields_set__这类内部管理属性,你跳过这一步直接给实例赋值,就会触发Pydantic的属性校验逻辑,而此时依赖的__fields_set__还不存在,自然报错。

而且更关键的是:Pydantic Settings本身就支持原生加载YAML配置,完全不需要你手动在__init__里读YAML再赋值,这属于重复造轮子还踩了坑。


正确配置方案(推荐,符合Pydantic设计)

因为你用的是pydantic-settings==2.4.0,建议直接用它的新版API,配合嵌套模型自动映射YAML结构,代码更简洁还不会出错。

步骤1:确保依赖齐全

先安装pyyaml(Pydantic需要它解析YAML文件):

pip install pyyaml

步骤2:编写配置类

用新版BaseSettings(来自pydantic_settings而非pydantic.v1),通过model_config指定YAML路径,用嵌套模型匹配YAML的层级结构:

from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import AnyHttpUrl, Field
from typing import List, Optional

# 嵌套模型:对应YAML里的kafka_consumer节点结构
class KafkaConsumerSettings(BaseSettings):
    host: str
    port: int
    kafka_topics: str

# 嵌套模型:对应YAML里的数据库配置节点
class DatabaseSettings(BaseSettings):
    user: Optional[str] = None
    password: Optional[str] = None
    host: Optional[str] = None
    port: Optional[str] = None
    name: Optional[str] = None
    sqlalchemy_database_url: Optional[str] = None

class ServiceSettingsYaml(BaseSettings):
    backend_cors_origins: List[AnyHttpUrl] = []
    kafka_consumer: KafkaConsumerSettings  # 自动映射YAML的kafka_consumer节点
    file_encoding: str = "utf-8"
    db: DatabaseSettings  # 自动映射YAML的db节点

    # 核心配置:指定YAML文件路径和编码
    model_config = SettingsConfigDict(
        yaml_file="configs/dev-config.yaml",
        env_file_encoding="utf-8"
    )

# 直接实例化,Pydantic会自动加载并解析YAML
settings = ServiceSettingsYaml()

# 测试访问配置
print(settings.kafka_consumer.host)  # 输出: kafka
print(settings.kafka_consumer.port)  # 输出: 9092
print(settings.db.host)  # 输出YAML里的db.host值

对应的YAML文件示例(configs/dev-config.yaml)

kafka_consumer:
  host: kafka
  port: 9092
  kafka_topics: my_topic
file_encoding: utf-8
db:
  user: my_db_user
  password: my_db_pass
  host: db
  port: 5432
  name: my_db_name

如果你坚持要用pydantic.v1的API(不推荐)

如果因为某些原因必须用pydantic.v1.BaseSettings,那一定要在__init__里先调用父类的初始化方法:

from pydantic.v1 import BaseSettings, AnyHttpUrl
from typing import List, Optional
import yaml

def load_yaml_config(config_path: str):
    with open(config_path, 'r', encoding='utf-8') as f:
        return yaml.safe_load(f)

class ServiceSettingsYaml(BaseSettings):
    backend_cors_origins: List[AnyHttpUrl] = []
    kafka_host: Optional[str] = None
    kafka_port: Optional[int] = None
    kafka_topics: Optional[str] = None
    file_encoding: str = "utf-8"
    # 其他数据库属性...

    def __init__(self, config_file_path: str = "configs/dev-config.yaml"):
        # 必须先调用父类__init__,初始化内部属性如__fields_set__
        super().__init__()
        config = load_yaml_config(config_file_path)
        
        # 现在再赋值就不会报错了
        self.kafka_host = config["kafka_consumer"]["host"]
        self.kafka_port = config["kafka_consumer"]["port"]
        self.kafka_topics = config["kafka_consumer"]["kafka_topics"]

# 实例化测试
settings = ServiceSettingsYaml()
print(settings.kafka_host)  # 输出: kafka

为什么这个方案能解决问题?

第一种推荐方案完全遵循Pydantic Settings的设计,它会自动处理:

  1. YAML文件的加载和解析
  2. 类型校验(比如把YAML里的port自动转成int)
  3. 嵌套结构的映射
  4. 内部属性的正确初始化(包括__fields_set__)

而第二种方案通过调用super().__init__()补全了父类的初始化流程,让Pydantic的内部属性正常创建,避免了报错。

备注:内容来源于stack exchange,提问作者mascai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 16:04:50