Pydantic讲解

1. 一句话解释 Pydantic

Pydantic 让你用 Python 的「类型注解」来定义数据的"蓝图",然后它会自动帮你校验、转换、清洗数据。

比如你写一个函数,希望 age 必须是整数,但外面传进来的是字符串 "18" ------ Pydantic 会自动把字符串 "18" 变成整数 18,如果转不了(比如 "abc")就报错。

2. 为什么需要它?

现实世界的数据往往是"脏"的:

用户表单:年龄 "25"(字符串)

JSON 文件:某个字段缺失

API 返回:字段类型乱写

你不想在代码里写满 if type(data['age']) is not int: ... 或者 try: int(age) ... ------ 太累了。

Pydantic 帮你统一处理这些问题,让你专注于业务逻辑。

bash 复制代码
#安装
pip install pydantic
#导入
from pydantic import BaseModel

3.定义模型

定义模型 = 继承 BaseModel + 类型注解

3.1 基础字段类型

直接用 Python 内置类型:str, int, float, bool, bytes, list, dict, tuple, set 等。

bash 复制代码
from pydantic import BaseModel

class BasicModel(BaseModel):
    a: str
    b: int
    c: float
    d: bool
    e: bytes
    f: list       # 任意列表
    g: dict       # 任意字典

3.2 使用 Field 添加约束和元数据

Field 可以给字段增加校验规则、默认值、描述等。

bash 复制代码
from pydantic import BaseModel, Field

class Product(BaseModel):
    name: str = Field(min_length=1, max_length=50, description="商品名称")
    price: float = Field(gt=0, description="价格必须大于0")
    stock: int = Field(default=0, ge=0, le=1000, description="库存0-1000")
    tags: list[str] = Field(default_factory=list)  # 默认空列表

常用约束参数:

gt, ge, lt, le:数值范围

min_length, max_length:字符串/列表长度

regex:正则表达式

default:默认值(静态值)

default_factory:默认值工厂(比如 list, dict,避免共享)

alias:字段别名(用于解析时不同的键名)

3.3 用 Literal 限制枚举值(精确取值)

bash 复制代码
from typing import Literal
from pydantic import BaseModel

class User(BaseModel):
    role: Literal["admin", "editor", "viewer"]   # 只能是这三个字符串之一

3.4 可选字段(Optional / None)

bash 复制代码
from typing import Optional

class Profile(BaseModel):
    nickname: Optional[str] = None   # 可以是 str 或 None,默认 None
    # 或者 Python 3.10+ 写法:
    age: int | None = None

3.5 嵌套模型(模型作为字段)

bash 复制代码
class Address(BaseModel):
    city: str
    street: str

class Person(BaseModel):
    name: str
    address: Address   # 嵌套模型

3.6 列表字段(包含特定类型)

bash 复制代码
class Order(BaseModel):
    items: list[str]           # 字符串列表
    prices: list[float]        # 浮点数列表
    coordinates: list[tuple[float, float]]  # 复杂一点

3.7 Union 联合类型(字段可以是多种类型之一)

bash 复制代码
from typing import Union

class Flexible(BaseModel):
    value: Union[int, str, None] = None   # 可以是 int, str, None

3.8 模型配置(model_config)

子类会「继承」父类的所有字段,然后可以再添加自己的新字段。

bash 复制代码
from pydantic import BaseModel

# 父类(基类)
class BaseUser(BaseModel):
    name: str
    email: str

# 子类(VipUser)继承了 BaseUser 的所有字段
class VipUser(BaseUser):
    vip_level: int = 1   # 子类自己新增的字段,默认值为 1

# 创建一个 VipUser 实例,必须提供 name 和 email(继承来的),也可以提供 vip_level(自己的)
vip = VipUser(name="张三", email="zhang@example.com", vip_level=5)

print(vip.name)        # 张三(继承来的)
print(vip.email)       # zhang@example.com(继承来的)
print(vip.vip_level)   # 5(自己的)

3.9 自定义校验器(@field_validator)

当内置规则不够用,可以写函数自定义验证逻辑。

bash 复制代码
from pydantic import BaseModel, field_validator

class User(BaseModel):
    username: str

    @field_validator('username')
    @classmethod
    def username_must_be_lowercase(cls, v: str) -> str:
        if not v.islower():
            raise ValueError('用户名必须全小写')
        return v

3.10 模型配置(model_config)

控制整个模型的行为,比如是否允许额外字段、是否自动转换等。

bash 复制代码
from pydantic import BaseModel, ConfigDict

class StrictModel(BaseModel):
    model_config = ConfigDict(extra='forbid')   # 禁止有未定义的字段
    name: str

3.11 计算字段(@property 或 @computed_field)

型中想有一个动态生成的只读属性。

bash 复制代码
from pydantic import BaseModel, computed_field

class Rectangle(BaseModel):
    width: float
    height: float

    @computed_field
    @property
    def area(self) -> float:
        return self.width * self.height

4. 自动验证 & 类型转换

当我们定义好模型类之后,就会实例化、校验数据、读取/修改数据、导出数据等。

4.1 创建实例并自动校验/转换

bash 复制代码
# 方式1:直接传关键字参数
user = User(name="Alice", age="25")   # age 字符串转 int

# 方式2:从字典创建
data = {"name": "Bob", "age": "30"}
user = User.model_validate(data)      # 推荐,2.x 版本

# 方式3:从 JSON 字符串创建
json_str = '{"name": "Charlie", "age": "35"}'
user = User.model_validate_json(json_str)

如果数据不合规,会抛出 pydantic.ValidationError。

4.2 访问和修改字段值

bash 复制代码
user = User(name="David", age=28)
print(user.name)      # David
user.age = 29         # 直接赋值(会再次校验新值)
bash 复制代码
#BaseSettings  从环境变量加载,会自动去环境变量里找字段名的大写形式。
class Settings(BaseSettings):
#ConfigDict 和 model_config 它们用来设置整个模型的行为规则,比如"允不允许多传字段"、"从哪个文件读配置"等。
    model_config = SettingsConfigDict(
        env_file=".env",          # 除了系统环境变量,还从 .env 文件读
        env_file_encoding="utf-8",
        extra="ignore",
    )

    tcvdb_database: str = Field(
        default="expert_kb",
        validation_alias=AliasChoices("TCVDB_DATABASE", "VDB_DATABASE")
    )

4.3 导出数据:到字典 / JSON

bash 复制代码
# 转字典
d = user.model_dump()       # {'name': 'David', 'age': 29}
# 转 JSON 字符串
j = user.model_dump_json()  # '{"name":"David","age":29}'

4.4 复制模型(浅拷贝或深拷贝)

bash 复制代码
user_copy = user.model_copy()           # 浅拷贝
user_copy2 = user.model_copy(deep=True) # 深拷贝

4.5 更新模型(部分修改)

可以用 model_copy(update={...}) 创建修改后的新模型:

bash 复制代码
new_user = user.model_copy(update={"age": 30})

4.6 查看模型结构信息(model_fields, model_json_schema)

bash 复制代码
print(User.model_fields)          # 字段定义
print(User.model_json_schema())   # JSON Schema(用于 API 文档等)

4.7 处理校验错误(捕获 ValidationError)

bash 复制代码
from pydantic import ValidationError

try:
    user = User(name="", age=-5)
except ValidationError as e:
    print(e.errors())   # 详细的错误列表
    print(e.json())     # JSON 格式的错误信息

4.8 忽略额外字段 / 严格模式

如果模型配置了 extra='forbid',使用时会拒绝多余字段;否则默认会忽略。

bash 复制代码
class ForbidExtra(BaseModel):
    model_config = ConfigDict(extra='forbid')
    name: str

# 下面会报错,因为 age 是额外字段
# f = ForbidExtra(name="Tom", age=20)   # ValidationError

4.9 异步环境中使用(model_validate 同步,但可结合 async/await)

Pydantic 本身是同步的,但它的校验函数可以在异步代码中直接调用,不会阻塞事件循环(因为是纯 CPU 操作)。

4.10 model_validator - 自定义验证

bash 复制代码
# 不转换(原始字符串)
class BadSettings(BaseModel):
    dir: str = "/tmp"

bad = BadSettings()
# 必须手动转
from pathlib import Path
print(Path(bad.dir) / "a.txt")

# -------------------------------------------------

# 转换后(自动变 Path)
class GoodSettings(BaseModel):
    dir: str = "/tmp"

    @model_validator(mode="after")
    def to_path(self):
        self.dir = Path(self.dir)
        return self

good = GoodSettings()
# 直接使用,无需转换
print(good.dir / "a.txt")

"模型创建完,upload_dir 就是 Path 对象" 意思是:你拿到实例后,不用再写 Path(...) 去转换,它已经是一个带方法的 Path 对象,可以直接用来操作文件和目录。

装饰器@model_validator告诉Pydantic在模型实例化过程中(验证完成后)自动调用这个方法,无需手动调用。

相关推荐
x***r15110 小时前
node-v0.12.2-x86安装步骤详解(附Node.js历史版本与32位配置教程)
windows
小小小米粒10 小时前
Collection单列集合、Map(Key - Value)双列集合,多继承实现。
java·开发语言·windows
蜡台11 小时前
Python包管理工具pip完全指南-----2
linux·windows·python
love530love16 小时前
Windows Podman Machine 虚拟硬盘迁移完整指南:从 C 盘到非系统盘
c语言·人工智能·windows·podman
love530love16 小时前
Podman Machine 虚拟硬盘迁移实战二:用 Junction 把 vhdx 从 C 盘搬到其他盘
c语言·开发语言·人工智能·windows·wsl·podman·podman machine
薛定猫AI18 小时前
【技术干货】Claude Code 终端编程实战:从零搭建 Windows 高效 AI 开发环境
人工智能·windows
V我五十买鸡腿1 天前
网安基础 Windows 和 Linux 那些常用命令
linux·运维·windows
shughui1 天前
2026最新JDK版本选择及下载安装详细图文教程【windows、mac附安装包】
java·linux·开发语言·windows·jdk·mac
这是程序猿1 天前
ComfyUI 教程合集|AI绘图、ControlNet、Lora、IPAdapter、视频生成全攻略
大数据·人工智能·windows·音视频