Pydantic 的 BaseSettings 配置解析

概述

最近在看一个开源项目 cognee ,其中有很多下面类似的pydantic配置文件,由于对 pydantic 没有深入了解,所以对 pydantic 中的 BaseSettings 的作用不是很了解。为了更清楚的了解 BaseSettings 的使用,通过查阅资料,本文记录一下其如何使用和配置。

python 复制代码
class EmbeddingConfig(BaseSettings):
    """
    Manage configuration settings for embedding operations, including provider, model
    details, API configuration, and tokenizer settings.

    Public methods:
    - to_dict: Serialize the configuration settings to a dictionary.
    """

    embedding_provider: Optional[str] = "openai"
    embedding_model: Optional[str] = "openai/text-embedding-3-large"
    embedding_dimensions: Optional[int] = 3072
    embedding_endpoint: Optional[str] = None
    embedding_api_key: Optional[str] = None
    embedding_api_version: Optional[str] = None
    embedding_max_tokens: Optional[int] = 8191
    huggingface_tokenizer: Optional[str] = None
    model_config = SettingsConfigDict(env_file=".env", extra="allow")  # 从环境变量或.env文件中填充模型的字段

pydantic 中的 BaseSettings 介绍

在Pydantic库中,BaseSettings是一个特殊的基类,用于定义配置管理模型。它扩展了Pydantic的BaseModel,专门用于处理应用程序的设置或配置,这些配置通常来自多个来源(如环境变量、配置文件、秘密管理等)。使用BaseSettings可以方便地管理和验证应用程序的配置。

主要作用:

  1. 多来源配置加载BaseSettings可以从多个来源加载配置,包括:
  • 环境变量(默认)

  • 环境文件(如.env文件)

  • 初始化时传入的字典或关键字参数

  • 其他自定义来源(通过重写类方法实现)

  1. 自动类型转换和验证 :和BaseModel一样,BaseSettings会对配置值进行类型转换和验证,确保配置项符合声明的类型和约束。

  2. 环境变量优先 :默认情况下,BaseSettings会优先从环境变量中读取配置,然后才是初始化参数或环境文件。这样便于在部署时通过环境变量覆盖配置。

  3. 敏感信息管理:支持从秘密管理服务(如Docker Secrets、Kubernetes Secrets)加载敏感数据。

使用示例:

下面是一个简单的BaseSettings使用示例:

python 复制代码
from pydantic_settings import BaseSettings, SettingsConfigDict

class AppSettings(BaseSettings):

    app_name: str = "My App"
    
    host: str = "localhost"
    
    port: int = 8000
    
    debug: bool = False
    
    model_config = SettingsConfigDict(env_file=".env", env_prefix="APP_")

在这个例子中:

  • 配置类AppSettings继承自BaseSettings

  • 定义了四个配置项,并提供了默认值。

  • 通过model_config指定了环境文件为.env,并且环境变量前缀为APP_

加载顺序:

当创建AppSettings实例时,配置的加载顺序如下(从高优先级到低优先级):

  1. 初始化参数(如AppSettings(port=8080)

  2. 环境变量(如APP_PORT

  3. 环境文件(如.env文件中的APP_PORT

  4. 类中字段的默认值

环境变量命名规则:

默认情况下,环境变量名由以下方式生成:

  • 将字段名转换为大写

  • 如果指定了env_prefix,则添加前缀

  • 嵌套模型的环境变量名使用双下号__分隔(由env_nested_delimiter配置,默认是双下划线)

例如,对于字段database_port,如果env_prefix设置为MYAPP_,则环境变量名为MYAPP_DATABASE_PORT

与普通BaseModel的区别:

特性 BaseModel BaseSettings
主要用途 数据验证和解析 应用程序配置管理
配置加载来源 仅初始化参数 环境变量、文件、初始化参数等
环境变量支持 有(默认)
环境文件支持 有(通过配置)
敏感信息管理 有(通过secrets配置)

高级用法:

  • 自定义来源 :通过重写customise_sources类方法,可以自定义配置加载的来源和顺序。

  • 嵌套模型 :支持嵌套模型,环境变量可以通过分隔符(如__)来设置嵌套字段。

  • 秘密管理 :通过secrets_dir指定目录,从文件中读取敏感信息(如SettingsConfigDict(secrets_dir="/run/secrets"))。

Pydantic 的 SettingsConfigDict 配置作用解析

在Pydantic中,SettingsConfigDict 是一个用于配置模型行为的类,特别是在处理设置(通常来自环境变量或.env文件)时。它替代了旧版本Pydantic(v1)中的Config内部类。

在前面提供的代码中,EmbeddingConfig类继承自BaseSettings(在pydantic_settings模块中)。 在这个类中,有一个类属性model_config,它被赋值为SettingsConfigDict的一个实例(在代码中是直接赋值,但通常我们会看到它被赋值为一个字典或一个SettingsConfigDict对象)。 这里,SettingsConfigDict的作用是配置EmbeddingConfig类的行为。具体来说:

  1. env_file=".env":指定从名为.env的文件中读取环境变量。这意味着Pydantic在加载设置时会读取项目根目录下的.env文件(如果存在的话),并将文件中的变量加载到环境变量中,然后这些环境变量会被用来填充模型的字段。例如:如果 .env 中有 EMBEDDING_API_KEY=sk-xxx,会自动赋值给 embedding_api_key 字段

  2. extra="allow":这个配置表示,如果模型在初始化时遇到了不在模型定义中的额外字段(extra fields),那么允许这些字段存在,并且将它们存储在模型的__pydantic_extra__属性中(而不是引发验证错误)。默认情况下,Pydantic模型会拒绝额外字段(即extra="forbid")。

总结一下,SettingsConfigDict在这里的作用是配置EmbeddingConfig类如何从环境变量(包括从.env文件加载)中获取设置,并且允许模型接受并存储额外的配置项(这些额外配置项虽然不会被用于模型定义的字段,但会被保留,可以通过 model_instance.__pydantic_extra__ 访问)。

注意:在旧版Pydantic(v1)中,我们通常使用内部类Config来设置这些配置,例如:

python 复制代码
class Config:
    env_file = ".env"
    extra = "allow"

而在Pydantic v2中,推荐使用model_config属性并赋值为SettingsConfigDict的实例(或者也可以直接赋值为一个字典,因为SettingsConfigDict本质上是一个字典的子类)。所以,这里使用的是Pydantic v2的方式。

另外,由于EmbeddingConfig继承自BaseSettings,它也会自动从环境变量中读取匹配的字段(不区分大小写,但通常使用大写)。例如,embedding_provider字段会尝试从环境变量EMBEDDING_PROVIDER中读取值。

所以,这个配置使得EmbeddingConfig类可以从.env文件中加载环境变量,并且允许在初始化时传入额外的配置项。

完整功能说明:

配置项 作用 示例值
env_file 从指定文件加载环境变量 ".env", [".env", ".prod"]
extra 处理未定义字段的策略 "allow", "ignore", "forbid"
env_prefix 环境变量前缀(自动添加) "APP_" → 读取 APP_API_KEY
case_sensitive 环境变量名是否区分大小写 False (默认不区分)
env_nested_delimiter 嵌套环境变量分隔符(如 DB__HOSTdb.host) "__"

典型使用场景:

python 复制代码
# .env 文件内容示例
EMBEDDING_PROVIDER=huggingface
EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
UNEXPECTED_SETTING=123  # 会被保留到 __pydantic_extra__
python 复制代码
# 使用配置
config = EmbeddingConfig()  # 自动加载 .env 中的设置

print(config.embedding_provider)  # 输出: "huggingface"
print(config.__pydantic_extra__)  # 输出: {"unexpected_setting": 123}

注意事项:

  1. 优先级顺序

    手动传入参数 > 环境变量 > .env 文件变量 > 类默认值

  2. 安全建议

    敏感字段(如 API keys)应通过环境变量传递,避免硬编码在代码或 .env 文件中

  3. Pydantic 版本

    • v1 使用内部 Config
    • v2 开始使用 model_config = SettingsConfigDict(...) 风格

通过这种配置,Pydantic 实现了灵活的环境感知设置加载,非常适合需要多环境部署的应用(开发/测试/生产)。

代码演示

python 复制代码
from pydantic_settings import BaseSettings, SettingsConfigDict
import os
class AppSettings(BaseSettings):

    app_name: str = "My App"
    
    host: str = "localhost"
    
    port: int = 8000
    
    debug: bool = False
    
    model_config = SettingsConfigDict(env_file=".env", env_prefix="APP_")

# 当创建`AppSettings`实例时,配置的加载顺序如下(从高优先级到低优先级):
print(f'默认参数 AppSettings() =====> {AppSettings()}')
# 1. 初始化参数(如`AppSettings(port=8080)`)
print(f'指定初始化参数 AppSettings(port=8080) =====> {AppSettings(port=8080)}')
# 2. 环境变量(如`APP_PORT`)
os.environ['APP_PORT'] = "8888"
print(f'设置环境变量os.environ["APP_PORT"] = "8888",AppSettings() =====> {AppSettings()}')
print(f'设置环境变量os.environ["APP_PORT"] = "8888",AppSettings(port=8080) =====> {AppSettings(port=8080)}')
ini 复制代码
默认参数 AppSettings() =====> app_name='My App' host='localhost' port=1 debug=False
指定初始化参数 AppSettings(port=8080) =====> app_name='My App' host='localhost' port=8080 debug=False
设置环境变量os.environ["APP_PORT"] = "8888",AppSettings() =====> app_name='My App' host='localhost' port=8888 debug=False
设置环境变量os.environ["APP_PORT"] = "8888",AppSettings(port=8080) =====> app_name='My App' host='localhost' port=8080 debug=False

最佳实践:

  1. 为敏感字段不设置默认值,强制从环境获取

  2. 使用 env_prefix 避免环境变量命名冲突

  3. 生产环境使用 secrets_dir 代替 .env 文件

    python 复制代码
    model_config = SettingsConfigDict(
        secrets_dir="/run/secrets",
        env_prefix="DB_"
    )

总结:

BaseSettings是Pydantic中用于管理应用程序配置的强大工具,它简化了从不同来源加载和验证配置的过程,特别是在云原生和容器化环境中,环境变量是配置的主要来源时非常有用,特别适合需要遵循 12-Factor App 原则的应用程序。

相关推荐
一个天蝎座 白勺 程序猿1 分钟前
Python爬虫(53)Python爬虫数据清洗与分析实战:Pandas+Great Expectations构建可信数据管道
爬虫·python·pandas
hu_nil2 分钟前
Python第七周作业
java·前端·python
秋水丶秋水4 分钟前
电脑桌面太单调,用Python写一个桌面小宠物应用。
开发语言·python·宠物
码码哈哈0.016 分钟前
NVIDIA CUDA 技术详解:开启 GPU 并行计算的大门
后端·ai
alpszero30 分钟前
使用VSCode开发Django指南
vscode·python·django·sqlite
大数据魔法师41 分钟前
MongoDB(八) - MongoDB GridFS介绍及使用Python操作GridFS
数据库·python·mongodb
weixin_377634841 小时前
【python异步多线程】异步多线程爬虫代码示例
开发语言·爬虫·python
struggle20251 小时前
PennyLane 是一个用于量子计算、量子机器学习和量子化学的跨平台 Python 库。由研究人员构建,用于研究
python·量子计算
扑克中的黑桃A1 小时前
Python-素数
python
扑克中的黑桃A1 小时前
Python学习的自我理解和想法(4)
python