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

如何避免pdoc泄露pydantic-settings的环境变量?

解决方案

方案1:自定义pdoc渲染钩子,修改变量显示

pdoc支持通过钩子函数自定义渲染逻辑,我们可以拦截模块中Settings实例的显示,仅输出类型名称而非具体值:

  1. 创建钩子文件pdoc_hook.py:
import pdoc.render.html

def custom_format_module_variable(value, ctx):
    # 仅对当前模块的Settings实例做处理
    if hasattr(ctx.module, 'Settings') and isinstance(value, ctx.module.Settings):
        return f"{type(value).__name__}"
    # 其他变量沿用默认格式化逻辑
    return pdoc.render.html.format_module_variable.__wrapped__(value, ctx)

# 替换默认的模块变量格式化函数
pdoc.render.html.format_module_variable = custom_format_module_variable
  1. 运行pdoc时指定钩子:
pdoc --hook pdoc_hook.py my_app

优点:无需修改业务代码,仅在文档生成时生效,运行时的__repr__完全不受影响。
缺点:需要维护额外的钩子文件,对pdoc版本有一定依赖(需确保钩子API兼容)。

方案2:模块级延迟初始化,避免pdoc扫描时实例化

通过模块的__getattr__实现SETTINGS的延迟加载,让pdoc在扫描模块时不会触发实例化,自然不会显示具体值:

# my_app/config.py
from pydantic_settings import BaseSettings
from typing import Optional

class Settings(BaseSettings):
    app_name: str = "Awesome API"
    admin_email: str
    items_per_user: int = 50

# 私有变量存储实例,初始为None
_SETTINGS: Optional[Settings] = None

def __getattr__(name):
    if name == "SETTINGS":
        global _SETTINGS
        if _SETTINGS is None:
            _SETTINGS = Settings()
        return _SETTINGS
    raise AttributeError(f"module {__name__} has no attribute {name}")

# 导出符号,确保其他模块可以正常导入
__all__ = ["SETTINGS", "Settings"]

"""
全局配置实例SETTINGS:
通过延迟加载机制初始化,包含应用的所有配置参数(来自config.yaml、.env及环境变量)。
其他模块可通过`from my_app.config import SETTINGS`直接访问。
"""

优点:业务代码改动小,完全隔离文档生成和运行时的实例化逻辑,不会泄露任何配置值。
缺点:需要理解模块级__getattr__的行为,首次访问SETTINGS时会触发初始化(对性能影响可忽略)。

方案3:基于环境变量控制__repr__输出

在Settings类的__repr__方法中判断当前是否处于文档生成环境,动态调整输出内容:

# my_app/config.py
import os
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str = "Awesome API"
    admin_email: str
    items_per_user: int = 50

    def __repr__(self):
        # 检测是否在pdoc生成环境
        if os.getenv("PDOC_BUILD"):
            return self.__class__.__name__
        # 运行时保留完整repr用于日志
        return super().__repr__()

SETTINGS = Settings()

运行pdoc时设置环境变量:

PDOC_BUILD=1 pdoc my_app

优点:逻辑简单直观,无需额外文件,仅在文档生成时修改输出。
缺点:需要确保文档生成流程中正确设置环境变量,否则仍会泄露值。

更优的跨模块配置共享方案

上述方案已能解决文档泄露问题,若要进一步优化配置共享:

  • 采用依赖注入(如FastAPI的Depends):在需要配置的地方通过Depends(get_settings)获取实例,而非直接导入模块变量,这种方式更易于测试(可替换测试配置)。
  • 使用单例模式封装:将get_settings函数封装成一个单例类,确保全局只有一个配置实例,同时提供清晰的访问入口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:07:35