python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python Pydantic数据校验

Python使用Pydantic进行数据校验的现代方案

作者:何以解忧,唯有..

在 Python 开发中,数据校验与解析是几乎每个项目都绕不开的环节,Pydantic 最初由 Samuel Colvin 于 2017 年创建,如今已成为 Python 生态中最受欢迎的库之一,本文将系统介绍 Pydantic 的核心概念与使用方法,帮助你快速上手这一强大的工具,需要的朋友可以参考下

1. 引言

在 Python 开发中,数据校验与解析是几乎每个项目都绕不开的环节。无论是从 API 接收 JSON 请求、读取配置文件,还是与数据库交互,我们都希望数据在进入业务逻辑之前就得到验证和规范化。Pydantic 正是为此而生的现代数据校验库,它基于 Python 类型提示(Type Hints)构建,让数据校验变得简洁、直观且高效。

Pydantic 最初由 Samuel Colvin 于 2017 年创建,如今已成为 Python 生态中最受欢迎的库之一。它不仅是 FastAPI 的数据校验基石,也被广泛应用于数据科学、配置管理、ORM 映射等众多场景。本文将系统介绍 Pydantic 的核心概念与使用方法,帮助你快速上手这一强大的工具。

2. 为什么选择 Pydantic

在 Pydantic 出现之前,Python 开发者通常使用手写校验逻辑或 schema 类库(如 Marshmallow、Schema)来处理数据验证。这些方案各有优劣,但普遍存在代码冗余、类型支持不完善或性能瓶颈等问题。

Pydantic 的核心优势体现在以下几个方面:

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)

常用约束参数包括:

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数据校验的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文