使用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文件是否存在,改为文件存在性检查:
确保Sphinx构建时能加载到正确的环境变量文件(如果存在)。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配置
在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列表:
注意这种方式会丢失Settings类的方法、验证规则等细节文档。autodoc_mock_imports = ["pydantic", "your_project.settings"]
内容的提问来源于stack exchange,提问作者Plaoo
相关产品推荐
相关产品推荐

