
Pydantic 是 Python 中最流行的数据验证 的第三方库,,它提供了一种声明式的方式来定义数据模型,基于类型注解 工作,具有高性能(核心验证逻辑用 Rust 编写)和优秀的 IDE 集成。
一、类型注解与验证
Pydantic 的核心是声明式数据建模 。通过继承 BaseModel 并定义带类型注解的类属性来声明数据模型。Pydantic 会自动进行:
-
数据验证:确保数据符合声明的类型。
-
数据转换(Coercion):在可能的情况下,自动将输入数据转换为声明的类型。
-
序列化:将模型实例导出为字典或 JSON。
二、快速上手:基础使用
1. 安装与导入
pip install pydantic
from datetime import datetime
from pydantic import BaseModel
from typing import Optional, Dict, List
2. 定义第一个模型
一个User模型,演示了不同类型的字段。
class User(BaseModel):
id: int # 必填字段,会尝试将 '1' 转为 1
name: str = "Jane Doe" # 有默认值,成为可选字段
signup_ts: Optional[datetime] = None # 可为空的 datetime
tastes: Dict[str, int] = {} # 字典类型,值为正整数
3. 数据验证与实例化
实例化时传入数据,Pydantic 会自动进行类型转换和验证。
# 这是外部数据,比如来自 API 或配置文件
external_data = {
'id': '123', # 注意:这是字符串
'signup_ts': '2024-10-01 12:00', # 字符串日期
'tastes': {
'wine': 5,
'cheese': 3,
},
}
# 实例化模型,验证并转换数据
user = User(**external_data)
# 访问属性(已转换为正确的类型)
print(user.id) # 输出: 123 (int)
print(user.signup_ts) # 输出: 2024-10-01 12:00:00 (datetime)
print(user.model_dump()) # 输出字典: {'id': 123, 'name': 'Jane Doe', ...}
4. 处理验证错误
当数据不符合规范时,Pydantic 会抛出 ValidationError 并提供清晰的错误信息。
from pydantic import ValidationError
invalid_data = {
'id': 'not_a_number', # 无法转为 int
'signup_ts': 'invalid_date', # 无法转为 datetime
}
try:
user = User(**invalid_data)
except ValidationError as e:
print(e.json()) # 打印结构化的错误报告
三、进阶功能:增强模型能力
1. 使用 Field 添加约束和描述
Field 函数可以给字段添加额外的验证规则(如长度、数值范围)和元数据。
from pydantic import BaseModel, Field
class Product(BaseModel):
name: str = Field(min_length=1, max_length=50, description="产品名称")
price: float = Field(ge=0, le=9999.99, description="产品价格")
stock: int = Field(default=0, ge=0, description="库存")
product = Product(name="Laptop", price=999.99)
print(product.model_dump()) # 输出: {'name': 'Laptop', 'price': 999.99, 'stock': 0}
备注 :这是 Pydantic 库的语法 ,BaseModel 在底层自动生成了 __init__ 方法,所以不需要手动写。Field 是用于添加字段描述的,不影响类型本身。
Field 常用参数:
| 参数 | 说明 | 示例 |
|---|---|---|
description |
字段描述(用于文档) | Field(description="用户姓名") |
default |
默认值 | Field(default="未知") |
min_length |
字符串最小长度 | Field(min_length=1) |
max_length |
字符串最大长度 | Field(max_length=100) |
ge |
数值 ≥ | Field(ge=0) |
le |
数值 ≤ | Field(le=100) |
example |
示例值(用于文档) | Field(example="张三") |
2. 嵌套模型与复杂类型
Pydantic 模型可以无缝嵌套,轻松处理复杂的 JSON 数据。
from typing import List
class Address(BaseModel):
city: str
street: str
class Student(BaseModel):
name: str
age: int
addresses: List[Address] # 嵌套模型列表
data = {
'name': 'Alice',
'age': 20,
'addresses': [{'city': 'Beijing', 'street': 'Chang'an Ave'}]
}
student = Student(**data)
print(student.addresses[0].city) # 输出: Beijing
3. 自定义验证器
使用 @field_validator 或 @model_validator 装饰器实现复杂的业务逻辑验证。
from pydantic import BaseModel, field_validator
class Order(BaseModel):
quantity: int
price: float
@field_validator('quantity')
@classmethod
def quantity_must_be_positive(cls, v: int) -> int:
if v <= 0:
raise ValueError('quantity must be greater than 0')
return v
@field_validator('price')
@classmethod
def price_must_be_positive(cls, v: float) -> float:
if v <= 0:
raise ValueError('price must be greater than 0')
return v
4. 严格模式
默认情况下 Pydantic 是"宽松"的(lax mode),会尝试转换类型。可以通过 model_config 启用严格模式来禁止类型转换。
from pydantic import BaseModel, ConfigDict
class StrictUser(BaseModel):
model_config = ConfigDict(strict=True)
id: int
# StrictUser(id='123') # 这会直接报错,因为输入的是字符串,而 strict=True
四、总结
| 特性 | 说明 | 使用场景 |
|---|---|---|
| 数据验证 | 通过类型注解和Field自动完成。 |
验证API请求、配置文件、环境变量。 |
| 类型转换 | 智能将"1"转为1,"2024-10-01"转为datetime。 |
处理来自HTTP查询参数或字符串配置的数据。 |
| 序列化 | .model_dump() 和 .model_dump_json() 方法。 |
将模型数据输出到数据库或响应API。 |
| 嵌套模型 | 模型可作为字段类型,完美对应复杂JSON。 | 处理具有层级结构的复杂数据。 |
| 错误处理 | ValidationError 提供详细且可编程的错误报告。 |
向客户端返回结构化的错误信息。 |
备注:
-
拥抱类型注解:用类型注解定义清晰的接口,充分利用 IDE 的自动补全和检查功能。
-
模型与业务分离:将 Pydantic 模型看作系统的"边界"(入口和出口)数据定义,而非内部业务逻辑对象。
-
善用
model_dump():在存储或传输数据时,应使用此方法显式导出数据,而不是直接访问__dict__。
更多用法可以参考中文官网介绍:https://pydantic.com.cn/