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

使用Sphinx生成文档遇Pydantic Settings验证错误无法生成相关文档

问题

使用Sphinx(apidoc)生成项目文档时,所有调用settings文件的文件均无法生成文档。执行make html命令时,出现以下错误:

#...
 File "pydantic/env_settings.py", line 39, in pydantic.env_settings.BaseSettings.__init__
  File "pydantic/main.py", line 342, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 35 validation errors for Settings
app_name
  field required (type=value_error.missing)
kafka_broker
  field required (type=value_error.missing)
apicurio_uri
  field required (type=value_error.missing)
jwt_secret
  field required (type=value_error.missing)
#...

Settings类基于Pydantic的BaseSettings编写,代码如下(settings.py):

class Settings(BaseSettings):
    app_name: str
    kafka_broker: str
    healthcheck_topic: str = "_healthcheck"

    # Apicurio
    apicurio_uri: str
    apicurio_journal_topic: str = "kafkasql-journal"

    business_rules_topic: str = "_message"

    jwt_secret: str
    jwt_expiration_sec: int = 24 * 60 * 60  # A day
    _jwt_algorithm: str = PrivateAttr(default_factory=lambda: "HS256")

    admin_username: str
    admin_password: str

    azure_auth_url: str
 
    class Config:
        try:
            env_file = '.env'
            env_file_encoding = 'utf-8'
            case_sensitive = False
        except:
            env_file = '.env_local'
            env_file_encoding = 'utf-8'
            case_sensitive = False


    def __init__(self, **data):
        super().__init__(**data)

        self._postgresql_conn = make_url(self.postgresql_conn_url)

    @property
    def postgresql_conn(self) -> URL:
        return self._postgresql_conn

    @property
    def jwt_algorithm(self) -> str:
        return self._jwt_algorithm


    @validator('redis_user', 'redis_password')
    def field_is_not_empty_if_not_null(cls, v):
        if v is not None and len(v) == 0:
            raise ValueError("Field cannot be empty string")

        return v

    _fields_not_empty = validator(
        'kafka_broker',
        'app_name',
        'apicurio_journal_topic',
        'business_rules_topic',
        'jwt_secret',
        allow_reuse=True
    )(field_not_empty)

    _fields_are_positive = validator(
        'cache_short_expiration_hours',
        'cache_medium_expiration_hours',
        'cache_long_expiration_hours',
        'jwt_expiration_sec',
        allow_reuse=True
    )(field_non_zero_positive)

    _fields_are_uri = validator(
        'apicurio_uri',
        'ticket_uri',
        allow_reuse=True
    )(field_is_uri)

    def build_api_definition(self) -> TicketApiDefinition:
        return TicketApiDefinition(

            webservice_endpoint=self.ticket_webservice_path,
            webservice_path=self.ticket_webservice_path,

            create_session=self.ticket_webservice_create_session_endpoint,

        )


@lru_cache
def get_settings():
    return Settings()

疑问:需要修改Sphinx配置还是调整Settings类来解决该问题?

解决方案

两种方式均可解决问题,可根据需求选择:

一、调整Settings类

让Settings在文档生成时跳过环境变量验证,或提供默认值:

  • 给必填字段添加占位默认值:给app_name、kafka_broker等必填字段添加默认值,比如app_name: str = "default_app",生产环境中环境变量会覆盖这些默认值,不影响正常运行,但能避免Sphinx加载时触发ValidationError。
  • 修改get_settings函数适配文档生成环境:通过环境变量判断是否处于Sphinx构建状态,传入测试数据初始化Settings:
    import os
    @lru_cache
    def get_settings():
        if os.getenv("SPHINX_BUILD") == "1":
            return Settings(
                app_name="test_app",
                kafka_broker="localhost:9092",
                apicurio_uri="http://localhost:8080",
                jwt_secret="test_secret",
                admin_username="admin",
                admin_password="admin",
                azure_auth_url="http://localhost:5000"
                # 补充其他必填字段
            )
        return Settings()
    
  • 修复Config类的异常逻辑:原Config类的try-except无法正确检测.env文件是否存在,改为文件存在性检查:
    from pathlib import Path
    class Config:
        env_file = '.env' if Path('.env').exists() else '.env_local'
        env_file_encoding = 'utf-8'
        case_sensitive = False
    
    确保Sphinx构建时能加载到正确的环境变量文件(如果存在)。

二、修改Sphinx配置

在conf.py中添加配置,避免触发Pydantic验证:

  • 设置环境变量并提前初始化Settings:在conf.py开头添加环境变量标识,或直接传入测试数据初始化Settings:
    import os
    os.environ["SPHINX_BUILD"] = "1"
    
    # 提前初始化Settings避免后续加载报错
    from your_project.settings import Settings
    Settings(
        app_name="test_app",
        kafka_broker="localhost:9092",
        # 补充其他必填字段
    )
    
  • 使用autodoc_mock_imports跳过模块加载:如果只需要生成结构文档,不需要实际加载Settings的实现,可将相关模块加入mock列表:
    autodoc_mock_imports = ["pydantic", "your_project.settings"]
    
    注意这种方式会丢失Settings类的方法、验证规则等细节文档。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:45:39