1. 引言
在 python 开发中,数据校验与解析是几乎每个项目都绕不开的环节。无论是从 api 接收 json 请求、读取配置文件,还是与数据库交互,我们都希望数据在进入业务逻辑之前就得到验证和规范化。pydantic 正是为此而生的现代数据校验库,它基于 python 类型提示(type hints)构建,让数据校验变得简洁、直观且高效。
pydantic 最初由 samuel colvin 于 2017 年创建,如今已成为 python 生态中最受欢迎的库之一。它不仅是 fastapi 的数据校验基石,也被广泛应用于数据科学、配置管理、orm 映射等众多场景。本文将系统介绍 pydantic 的核心概念与使用方法,帮助你快速上手这一强大的工具。
2. 为什么选择 pydantic
在 pydantic 出现之前,python 开发者通常使用手写校验逻辑或 schema 类库(如 marshmallow、schema)来处理数据验证。这些方案各有优劣,但普遍存在代码冗余、类型支持不完善或性能瓶颈等问题。
pydantic 的核心优势体现在以下几个方面:
- 基于类型提示:直接利用 python 原生类型注解定义数据模型,无需学习额外的 dsl(领域特定语言)。
- 性能卓越:核心逻辑使用 rust 编写(pydantic v2),校验速度远超同类纯 python 实现。
- 自动类型转换:在严格校验的同时,能智能地将输入数据转换为目标类型,如将字符串
"123"转为整数123。 - 丰富的验证器:内置大量字段约束(如长度、范围、正则),并支持自定义验证逻辑。
- 序列化与反序列化:轻松实现模型与 json、字典之间的相互转换。
- 与生态无缝集成:fastapi、django、sqlalchemy 等主流框架均提供官方或第三方集成。
3. 安装与基础用法
3.1 安装 pydantic
pydantic v2 要求 python 3.8 及以上版本,推荐使用 python 3.10+。使用 pip 即可完成安装:
pip install pydantic
安装完成后,可以通过以下命令验证版本:
python -c "import pydantic; print(pydantic.__version__)"
3.2 第一个模型
pydantic 的核心是 basemodel 基类。我们通过继承它并声明带类型注解的类属性来定义数据模型:
from pydantic import basemodel
class user(basemodel):
name: str
age: int
email: str
创建模型实例时,pydantic 会自动校验输入数据:
user = user(name="张三", age=25, email="zhangsan@example.com") print(user) # name='张三' age=25 email='zhangsan@example.com'
如果传入的数据类型不匹配,pydantic 会尝试进行类型转换:
user = user(name="李四", age="30", email="lisi@example.com") print(user.age, type(user.age)) # 30 <class 'int'>
当数据无法通过校验时,pydantic 会抛出 validationerror 异常:
from pydantic import validationerror
try:
user(name="王五", age="abc", email="wangwu@example.com")
except validationerror as e:
print(e)
4. 字段类型与约束
4.1 常用内置类型
pydantic 支持 python 标准库中的绝大多数类型,包括 str、int、float、bool、list、dict、tuple、set 等,同时也支持 typing 模块中的泛型类型:
from typing import optional, list, dict, union
from pydantic import basemodel
class order(basemodel):
order_id: int
items: list[str]
metadata: dict[str, str]
discount: optional[float] = none
status: union[str, int] = "pending"
4.2 字段约束
pydantic 通过 field 函数为字段添加更细致的约束条件:
from pydantic import basemodel, field
class product(basemodel):
name: str = field(..., min_length=1, max_length=50)
price: float = field(..., gt=0, le=10000)
quantity: int = field(0, ge=0)
description: str = field(default="", max_length=200)
常用约束参数包括:
min_length/max_length:字符串长度限制gt/ge/lt/le:数值大小限制(大于、大于等于、小于、小于等于)pattern:正则表达式匹配default:默认值default_factory:默认值工厂函数,用于生成动态默认值
4.3 正则表达式校验
from pydantic import basemodel, field
class account(basemodel):
username: str = field(..., pattern=r"^[a-za-z0-9_]{3,20}$")
phone: str = field(..., pattern=r"^1[3-9]\d{9}$")
5. 高级校验:验证器
5.1 字段级验证器
当内置约束无法满足需求时,可以使用 @field_validator 装饰器编写自定义验证逻辑:
from pydantic import basemodel, field_validator
class registration(basemodel):
username: str
password: str
confirm_password: str
@field_validator("username")
@classmethod
def username_not_admin(cls, v: str) -> str:
if v.lower() == "admin":
raise valueerror("用户名不能为 admin")
return v
@field_validator("confirm_password")
@classmethod
def passwords_match(cls, v: str, info) -> str:
if "password" in info.data and v != info.data["password"]:
raise valueerror("两次输入的密码不一致")
return v
5.2 模型级验证器
@model_validator 用于验证整个模型,适合处理字段间相互依赖的逻辑:
from pydantic import basemodel, model_validator
class daterange(basemodel):
start_date: str
end_date: str
@model_validator(mode="after")
def check_date_range(self):
if self.start_date > self.end_date:
raise valueerror("开始日期不能晚于结束日期")
return self
6. 数据序列化与解析
6.1 模型转字典与 json
user = user(name="张三", age=25, email="zhangsan@example.com")
# 转字典
data = user.model_dump()
print(data)
# {'name': '张三', 'age': 25, 'email': 'zhangsan@example.com'}
# 转 json 字符串
json_str = user.model_dump_json()
print(json_str)
# {"name":"张三","age":25,"email":"zhangsan@example.com"}
6.2 从字典与 json 解析
# 从字典创建
data_dict = {"name": "李四", "age": 30, "email": "lisi@example.com"}
user = user.model_validate(data_dict)
# 从 json 字符串创建
json_str = '{"name": "王五", "age": 28, "email": "wangwu@example.com"}'
user = user.model_validate_json(json_str)
7. 嵌套模型与复杂结构
pydantic 支持模型嵌套,非常适合处理层级化的数据结构:
from typing import list
from pydantic import basemodel
class address(basemodel):
city: str
street: str
zip_code: str
class customer(basemodel):
name: str
address: address
orders: list[dict] = []
嵌套模型的使用方式与普通模型一致:
customer = customer(
name="赵六",
address={"city": "北京", "street": "中关村大街", "zip_code": "100080"},
orders=[{"order_id": 1, "amount": 99.9}],
)
print(customer.address.city)
# 北京
8. 配置管理:settings 模型
pydantic 的 basesettings 类(需安装 pydantic-settings 包)非常适合管理应用配置,支持从环境变量、.env 文件等来源自动读取配置:
pip install pydantic-settings
from pydantic_settings import basesettings
class settings(basesettings):
app_name: str = "my app"
debug: bool = false
database_url: str
class config:
env_file = ".env"
settings = settings() print(settings.database_url)
9. 实战示例:构建一个用户注册接口
下面结合 fastapi 展示 pydantic 在实际项目中的典型用法:
from fastapi import fastapi, httpexception
from pydantic import basemodel, emailstr, field
app = fastapi()
class userregister(basemodel):
username: str = field(..., min_length=3, max_length=20)
email: emailstr
password: str = field(..., min_length=8)
class userresponse(basemodel):
username: str
email: emailstr
@app.post("/register", response_model=userresponse)
async def register(user: userregister):
# 模拟用户创建逻辑
return userresponse(username=user.username, email=user.email)
在这个示例中,fastapi 自动利用 pydantic 模型完成请求体的解析与校验,并确保响应数据符合 userresponse 的结构。
10. 总结
pydantic 凭借其简洁的语法、强大的类型支持和卓越的性能,已成为 python 数据校验领域的事实标准。本文从基础模型定义、字段约束、验证器、序列化到嵌套模型和配置管理,系统介绍了 pydantic 的核心功能。
在实际项目中,建议从简单的模型开始,逐步引入验证器和嵌套结构,让数据层始终保持清晰和健壮。结合 fastapi 等框架使用时,pydantic 能显著提升开发效率,减少大量重复的校验代码。
以上就是python使用pydantic进行数据校验的现代方案的详细内容,更多关于python pydantic数据校验的资料请关注代码网其它相关文章!
发表评论