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在模型实例化过程中(验证完成后)自动调用这个方法,无需手动调用。