python环境搭建 (十二) pydantic和pydantic-settings类型验证与解析

pydantic==2.12.5 核心库的功能/用法,以及配套的 pydantic-settings 库的作用,我会从核心功能、核心用法、pydantic-settings 专属用法三部分讲解,贴合 2.12.5 最新版特性,同时兼顾新手易理解性。

一、pydantic==2.12.5 核心功能

Pydantic 是 Python 中强类型数据验证与解析的主流库,2.x 版本相比 1.x 重写了核心代码,性能提升 5-10 倍,同时保留了易用性,核心能力包括:

  1. 数据验证:基于Python类型注解,自动校验输入数据的类型、范围、格式等,不符合规则则抛出清晰的异常;
  2. 数据解析/转换:自动将非标准输入(如字符串转数字、json字符串转字典)转换为注解指定的类型,无需手动处理;
  3. 数据建模 :通过定义BaseModel模型类,实现结构化数据的统一管理(类似ORM模型,但专注于数据校验而非数据库);
  4. 支持复杂类型 :原生支持列表、字典、嵌套模型、枚举、Union、Optional等Python内置类型,以及Pydantic自定义类型(如EmailStrUrlStr);
  5. 灵活的配置:支持字段默认值、可选字段、必选字段、自定义校验规则、别名等;
  6. 序列化/反序列化:轻松将模型转换为字典、JSON,或从字典/JSON实例化模型,适配API开发、配置解析等场景。

简单来说:Pydantic 让你用「类型注解」快速定义「结构化数据规则」,自动完成「校验+转换+建模」,告别手动写大量if判断的校验代码

二、pydantic==2.12.5 基本用法

前置准备

先安装核心库(2.12.5 版本):

bash 复制代码
pip install pydantic==2.12.5
核心基类:BaseModel

所有Pydantic数据模型都继承自 pydantic.BaseModel,通过类型注解定义字段规则,核心用法分「模型定义、实例化、数据操作、校验规则」四部分。

1. 基础模型定义与实例化

最核心的用法,定义模型后实例化,自动完成校验和转换:

python 复制代码
from pydantic import BaseModel, Field
from typing import Optional, List

# 定义数据模型(继承BaseModel)
class User(BaseModel):
    # 必选字段:str类型
    name: str
    # 必选字段:int类型,自动转换(如输入字符串"20"会转成20)
    age: int
    # 可选字段:None | List[str],默认值None
    hobbies: Optional[List[str]] = None
    # 带字段配置的字段:默认值0,别名"phone_num"(适配外部数据的键名),描述用于文档
    phone: int = Field(default=0, alias="phone_num", description="用户手机号")

# 1. 正常实例化(符合规则)
user1 = User(name="张三", age=20, hobbies=["篮球", "游戏"], phone_num=13800138000)
print(user1.name)  # 张三
print(user1.phone)  # 13800138000(自动映射别名)
print(user1.hobbies)  # ['篮球', '游戏']

# 2. 自动类型转换(输入字符串age,转成int)
user2 = User(name="李四", age="25", phone_num="13900139000")  # 字符串"25"→25,"13900139000"→int
print(type(user2.age))  # <class 'int'>
print(type(user2.phone))  # <class 'int'>

# 3. 校验失败(抛出清晰异常)→ age传非数字、必选字段缺失都会报错
# user3 = User(name="王五", age="二十")  # 报错:Input should be a valid integer, got a string
2. 模型的核心数据操作

Pydantic模型提供了便捷的方法,实现模型↔字典/JSON的转换,适配API、配置等场景:

python 复制代码
# 接上面的User模型,实例化user1
user1 = User(name="张三", age=20, hobbies=["篮球", "游戏"], phone_num=13800138000)

# 1. 转字典:model_dump()(2.x 替代1.x的dict())
print(user1.model_dump())
# 输出:{'name': '张三', 'age': 20, 'hobbies': ['篮球', '游戏'], 'phone': 13800138000}

# 2. 转JSON字符串:model_dump_json()
print(user1.model_dump_json(indent=2))  # indent=2 格式化输出
# 输出:
# {
#   "name": "张三",
#   "age": 20,
#   "hobbies": ["篮球", "游戏"],
#   "phone": 13800138000
# }

# 3. 从字典实例化模型(直接传参,或用model_validate())
user_dict = {"name": "赵六", "age": 30, "phone_num": 13700137000}
user4 = User.model_validate(user_dict)  # 等价于 User(**user_dict)
print(user4.name)  # 赵六

# 4. 从JSON字符串实例化:model_validate_json()
user_json = '{"name": "孙七", "age": 28, "phone_num": 13600136000}'
user5 = User.model_validate_json(user_json)
print(user5.age)  # 28
3. 常用校验规则(字段约束/自定义校验)

Pydantic 提供了内置约束 (通过Field)和自定义校验器 ,满足复杂的业务校验需求,2.x 推荐用@field_validator装饰器做字段校验。

(1)内置约束(Field 常用参数)

通过Field设置字段的范围、长度、正则等,无需手写校验:

python 复制代码
from pydantic import BaseModel, Field
from typing import Annotated

# 常用Field参数:gt(大于)、ge(大于等于)、lt(小于)、le(小于等于)、min_length、max_length、pattern(正则)
class Product(BaseModel):
    # 商品名:至少2个字符,最多20个字符
    name: str = Field(min_length=2, max_length=20)
    # 价格:大于0的浮点数
    price: float = Field(gt=0, description="商品价格,必须大于0")
    # 手机号:正则匹配中国大陆手机号
    phone: str = Field(pattern=r"^1[3-9]\d{9}$")

# 正常实例化
p1 = Product(name="苹果15", price=5999.99, phone="13800138000")
# 校验失败:价格≤0、手机号格式错误、商品名长度不够
# p2 = Product(name="果", price=-100, phone="123456")  # 抛出多个异常,清晰提示
(2)自定义字段校验器(@field_validator)

处理内置约束无法满足的个性化校验,比如「年龄必须是成年人(≥18)」「密码必须包含字母和数字」:

python 复制代码
from pydantic import BaseModel, Field, field_validator
from typing import Optional

class User(BaseModel):
    name: str
    age: int = Field(ge=0)
    password: str

    # 自定义校验器:校验age必须≥18(成年人)
    # mode="after":表示在校验器执行前,Pydantic已完成基础类型校验(如age是int)
    @field_validator("age", mode="after")
    def check_adult(cls, v):
        if v < 18:
            raise ValueError("年龄必须是成年人(≥18岁)")
        return v

    # 自定义校验器:校验密码必须包含字母和数字,长度≥6
    @field_validator("password")
    def check_password(cls, v):
        if len(v) < 6:
            raise ValueError("密码长度必须≥6")
        if not (any(c.isalpha() for c in v) and any(c.isdigit() for c in v)):
            raise ValueError("密码必须同时包含字母和数字")
        return v

# 正常实例化
user1 = User(name="张三", age=20, password="Abc123456")
# 校验失败
# user2 = User(name="李四", age=17, password="123456")  # 报错:年龄必须是成年人(≥18岁)
# user3 = User(name="王五", age=25, password="abcdef")    # 报错:密码必须同时包含字母和数字
4. 嵌套模型(复杂结构化数据)

支持模型嵌套模型,实现多层级数据的校验,比如「用户模型包含地址模型」:

python 复制代码
from pydantic import BaseModel
from typing import Optional

# 子模型:地址
class Address(BaseModel):
    province: str
    city: str
    detail: Optional[str] = None  # 详细地址,可选

# 父模型:用户(包含地址模型)
class User(BaseModel):
    name: str
    age: int
    address: Address  # 嵌套Address模型,必选

# 实例化:嵌套传参(字典形式)
user1 = User(
    name="张三",
    age=20,
    address={"province": "广东省", "city": "深圳市", "detail": "南山区科技园"}
)
# 访问嵌套字段
print(user1.address.province)  # 广东省
print(user1.address.detail)    # 南山区科技园

# 校验失败:嵌套字段缺失
# user2 = User(name="李四", age=25, address={"province": "北京市"})  # 报错:Address缺少city字段

三、pydantic-settings 功能与基本用法

pydantic-settings 是 Pydantic 官方推出的配置管理库 ,基于 Pydantic 核心的校验能力,专门用于从多源读取配置、统一管理项目配置 ,解决了Python传统配置(如os.getenv)的痛点:

  1. 手动转换环境变量类型(环境变量默认都是字符串,需手动转int/bool);
  2. 配置分散(环境变量、配置文件、命令行参数),难以统一管理;
  3. 无校验,配置错误只有运行时才会发现。
核心功能
  1. 自动从环境变量、.env文件、配置类默认值读取配置,支持多源优先级(环境变量 > .env文件 > 默认值);
  2. 基于Pydantic类型注解,自动校验+转换配置值(如字符串"True"转bool,"8000"转int);
  3. 支持配置嵌套、自定义配置源(如YAML/JSON配置文件);
  4. 与Pydantic核心库无缝兼容,语法一致。
前置准备

安装 pydantic-settings(与pydantic 2.x 配套,无需指定版本,会自动适配):

bash 复制代码
pip install pydantic-settings
核心基类:BaseSettings

所有Pydantic配置模型都继承自 pydantic_settings.BaseSettings语法与Pydantic的BaseModel完全一致,核心差异是「自动读取多源配置」。

1. 基础配置定义(读取环境变量/.env文件)
步骤1:定义配置模型(继承BaseSettings)
python 复制代码
# settings.py
from pydantic_settings import BaseSettings
from pydantic import Field
from typing import Optional

# 项目配置模型(继承BaseSettings)
class Settings(BaseSettings):
    # 服务配置
    API_HOST: str = Field(default="127.0.0.1", description="API服务地址")
    API_PORT: int = Field(default=8000, description="API服务端口")
    # 调试模式:环境变量传"True"/"true"/"1"会自动转bool,"False"/"0"转False
    DEBUG: bool = Field(default=False, description="调试模式")
    # 数据库配置
    DB_URL: str = Field(default="sqlite:///./db.sqlite3", description="数据库连接地址")
    # 可选配置
    REDIS_HOST: Optional[str] = Field(default=None, description="Redis地址")

    # 【关键配置】指定.env文件路径(默认读取项目根目录的.env文件,可自定义)
    class Config:
        env_file = ".env"  # 读取.env文件的环境变量
        env_file_encoding = "utf-8"  # .env文件编码

# 实例化配置(全局单例,项目中其他地方直接导入即可)
settings = Settings()

# 测试:打印配置
if __name__ == "__main__":
    print(f"API地址:{settings.API_HOST}:{settings.API_PORT}")
    print(f"调试模式:{settings.DEBUG}")
    print(f"数据库地址:{settings.DB_URL}")
步骤2:创建.env文件(项目根目录)

.env 文件是键值对格式的配置文件,Pydantic-settings 会自动读取其中的配置,键名与模型字段名一致

ini 复制代码
# .env 文件(项目根目录)
API_HOST=0.0.0.0
API_PORT=8080
DEBUG=True
DB_URL=mysql+pymysql://root:123456@localhost:3306/test
REDIS_HOST=127.0.0.1
步骤3:运行测试

直接运行settings.py,会自动读取.env文件的配置,并完成类型转换:

bash 复制代码
python settings.py

输出结果:

复制代码
API地址:0.0.0.0:8080
调试模式:True
数据库地址:mysql+pymysql://root:123456@localhost:3306/test
2. 多源配置的优先级

Pydantic-settings 读取配置的优先级从高到低
运行时手动传参 > 系统环境变量 > .env文件配置 > 模型默认值

举个例子:

  1. 系统环境变量设置 API_PORT=9000
  2. .env文件设置 API_PORT=8080
  3. 模型默认值 API_PORT=8000
    运行后settings.API_PORT的值是9000(系统环境变量优先级更高)。

如何设置系统环境变量

  • Linux/Mac 终端:export API_PORT=9000 && python settings.py
  • Windows CMD:set API_PORT=9000 && python settings.py
  • Windows PowerShell:$env:API_PORT=9000; python settings.py
3. 配置的使用(项目全局导入)

项目中其他模块直接导入settings实例即可使用配置,无需重复定义,实现配置统一管理

python 复制代码
# main.py
from settings import settings
import uvicorn
from fastapi import FastAPI

app = FastAPI(debug=settings.DEBUG)

@app.get("/")
def root():
    return {"message": "Hello Pydantic", "port": settings.API_PORT}

if __name__ == "__main__":
    uvicorn.run(app, host=settings.API_HOST, port=settings.API_PORT)
4. 嵌套配置模型(复杂配置)

与Pydantic的BaseModel一样,BaseSettings也支持嵌套,适合将不同模块的配置拆分(如数据库、Redis、日志):

python 复制代码
from pydantic_settings import BaseSettings
from pydantic import Field

# 数据库子配置
class DBConfig(BaseSettings):
    url: str = Field(default="sqlite:///./db.sqlite3")
    pool_size: int = Field(default=10)
    echo: bool = Field(default=False)  # 是否打印SQL语句

# Redis子配置
class RedisConfig(BaseSettings):
    host: str = Field(default="127.0.0.1")
    port: int = Field(default=6379)
    db: int = Field(default=0)

# 全局主配置(嵌套子配置)
class Settings(BaseSettings):
    api_host: str = Field(default="127.0.0.1")
    api_port: int = Field(default=8000)
    debug: bool = Field(default=False)
    db: DBConfig = DBConfig()  # 嵌套数据库配置
    redis: RedisConfig = RedisConfig()  # 嵌套Redis配置

    model_config = SettingsConfigDict(
        env_file=".env",        # 读取项目根目录的.env文件
        env_file_encoding="utf-8",
        case_sensitive=False    # 环境变量大小写不敏感(DB_HOST和db_host都生效)
    )

# 实例化
settings = Settings()
# 访问嵌套配置
print(settings.db.url)
print(settings.redis.port)

对应的.env文件可通过点语法设置嵌套配置:

ini 复制代码
api_host=0.0.0.0
api_port=8080
debug=True
# 嵌套数据库配置(点语法)
db.url=mysql+pymysql://root:123456@localhost:3306/test
db.pool_size=20
db.echo=True
# 嵌套Redis配置
redis.host=192.168.1.100
redis.port=6379
redis.db=1

四、pydantic vs pydantic-settings 核心区别

核心基类 核心用途 关键特性
pydantic==2.12.5 BaseModel 通用数据校验、建模、解析 类型注解校验、自动转换、序列化
pydantic-settings BaseSettings 项目配置管理(多源读取) 继承BaseModel能力+自动读环境变量/.env

核心关联BaseSettingsBaseModel 的子类,因此pydantic的所有用法(Field、校验器、嵌套、序列化)在pydantic-settings中都能直接使用,只是增加了「配置源读取」的能力。

五、2.x 版本关键注意点(避坑)

你使用的是pydantic 2.12.5,相比1.x有部分API废弃/更名,新手需注意:

  1. 转字典用 model_dump() 替代 1.x 的 dict()
  2. 转JSON用 model_dump_json() 替代 1.x 的 json()
  3. 从字典校验实例化用 model_validate() 替代 1.x 的 parse_obj()
  4. 从JSON校验实例化用 model_validate_json() 替代 1.x 的 parse_raw()
  5. 字段校验器用 @field_validator 替代 1.x 的 @validator,且新增mode参数;
  6. 全局配置从模型的Config类设置(如env_filealias_generator),语法不变。

总结

  1. pydantic==2.12.5 是Python强类型数据校验的核心库,通过BaseModel+类型注解,实现数据建模、自动校验、类型转换、序列化,告别手动校验代码,是API开发、数据处理的必备工具;
  2. pydantic-settings 是Pydantic官方的配置管理库,基于BaseSettings(BaseModel子类),在Pydantic核心能力基础上,增加了从环境变量/.env文件自动读取配置的能力,解决了Python配置管理的痛点;
  3. 两者语法高度一致,pydantic-settings 完全继承pydantic的所有特性(嵌套、校验器、Field等),仅新增配置源相关能力;
  4. 项目中常用搭配:pydantic 做接口参数/数据校验pydantic-settings 做项目全局配置管理(如数据库、服务端口、环境变量)。
相关推荐
前端玖耀里1 小时前
如何使用python的boto库和SES发送电子邮件?
python
小天源1 小时前
Error 1053 Error 1067 服务“启动后立即停止” Java / Python 程序无法后台运行 windows nssm注册器下载与报错处理
开发语言·windows·python·nssm·error 1053·error 1067
lekami_兰2 小时前
Java 并发工具类详解:4 大核心工具 + 实战场景,告别 synchronized
java·并发工具
_运维那些事儿2 小时前
VM环境的CI/CD
linux·运维·网络·阿里云·ci/cd·docker·云计算
有位神秘人2 小时前
Android中Notification的使用详解
android·java·javascript
云小逸2 小时前
【nmap源码学习】 Nmap网络扫描工具深度解析:从基础参数到核心扫描逻辑
网络·数据库·学习
喵手2 小时前
Python爬虫实战:HTTP缓存系统深度实战 — ETag、Last-Modified与requests-cache完全指南(附SQLite持久化存储)!
爬虫·python·爬虫实战·http缓存·etag·零基础python爬虫教学·requests-cache
喵手2 小时前
Python爬虫实战:容器化与定时调度实战 - Docker + Cron + 日志轮转 + 失败重试完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·容器化·零基础python爬虫教学·csv导出·定时调度
2601_949146532 小时前
Python语音通知接口接入教程:开发者快速集成AI语音API的脚本实现
人工智能·python·语音识别