【Python】Pydantic:快速上手

Pydantic 是一个用于数据验证和设置管理的 Python 库,基于 Python 类型提示构建。它通过创建数据模型类并使用类型提示进行数据验证,使得数据的验证和解析变得简单而可靠,广泛应用于数据模型的定义和验证,特别是在构建 API 时。

Python 类型提示

Python 的类型提示(Type Hinting)是一种可选的静态类型检查机制,通过在代码中添加类型注释来帮助开发者更好地理解代码的预期行为,从而提高代码的可读性和可维护性。类型提示不会影响代码的运行时行为,它只是作为开发工具的辅助。

基本类型

  • int:整数类型
  • float:浮点数类型
  • str:字符串类型
  • bool:布尔类型
def add(a: int, b: int) -> int:
    return a + b

集合类型

  • List[T]:表示元素类型为 T 的列表
  • Tuple[T1, T2, ...]:表示固定长度的元组,元素类型可以不同
  • Dict[K, V]:表示键为 K 类型、值为 V 类型的字典
  • Set[T]:表示元素类型为 T 的集合
from typing import List, Dict

def process_items(items: List[int], mapping: Dict[str, int]) -> None:
    pass

Optional 类型

  • Optional[T]:表示 T 类型或 None
from typing import Optional

def get_name(id: int) -> Optional[str]:
    if id == 0:
        return None
    return "Name"

Union 类型

  • Union[T1, T2, ...]:表示可能是多种类型之一
from typing import Union

def process(value: Union[int, str]) -> None:
    pass

Callable 类型

  • Callable[[Arg1, Arg2, ...], ReturnType]:表示可以调用的对象,接受参数和返回值类型
from typing import Callable

def apply(func: Callable[[int], str], value: int) -> str:
    return func(value)

Pydantic 主要功能

Pydantic 是一个强大的 Python 库,用于数据验证和解析,特别适合用于构建 API 和处理复杂的数据结构。以下是 Pydantic 主要功能的详细介绍和原理分析:

数据验证

Pydantic 通过使用 Python 类型提示自动验证输入数据的类型。它确保传递给模型的数据符合定义的类型要求,并支持复杂的数据结构和嵌套验证。

from pydantic import BaseModel, ValidationError

class User(BaseModel):
    id: int
    name: str
    email: str

try:
    user = User(id=1, name='John Doe', email='[email protected]')
except ValidationError as e:
    print(e)
  • 类型检查:Pydantic 在模型实例化时会检查传入的数据是否符合模型字段定义的类型。如果数据类型不匹配,会抛出 ValidationError
  • 复杂数据结构:对于嵌套模型,Pydantic 会递归验证嵌套的数据结构。例如,User 模型中的 Address 字段如果是另一个 Pydantic 模型,也会进行验证。
  • 动态校验:类型校验不仅限于基本数据类型,还支持通过类型注解定义的复杂数据类型,如 ListDict 和自定义类。

数据解析

Pydantic 可以将原始数据(如 JSON 字符串或字典)解析为 Pydantic 模型实例。这使得从外部数据源(如 API 响应)导入数据并转换为内部使用的对象变得非常简单。

from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
    email: str

user_data = {"id": 1, "name": "John Doe", "email": "[email protected]"}
user = User(**user_data)
  • 解包参数:Pydantic 允许通过 ** 运算符将字典中的键值对解包为模型实例的字段。Pydantic 会将这些字段值传递给模型构造函数。
  • 数据转换:如果输入数据类型与字段类型不匹配(例如,字符串 '1' 需要转换为整数 1),Pydantic 会尝试进行合理的转换,前提是转换合法且安全。

数据序列化

Pydantic 支持将模型实例转换为 JSON 格式或其他类型的数据结构,便于数据存储、传输和显示。

user_json = user.json()
  • JSON 序列化:调用 .json() 方法会将模型实例转换为 JSON 字符串。Pydantic 会将字段值转换为 JSON 格式支持的数据类型。
  • 自定义序列化:通过定义 json_encoders 配置项,可以自定义模型字段的序列化方式。例如,将日期对象转换为特定格式的字符串。

自定义验证

Pydantic 允许使用 @validator 装饰器定义自定义验证逻辑,以满足特定的验证需求。

from pydantic import BaseModel, validator

class User(BaseModel):
    id: int
    name: str
    email: str

    @validator('email')
    def email_must_contain_at(cls, v):
        if '@' not in v:
            raise ValueError('Email must contain @')
        return v
  • 装饰器功能@validator 装饰器用于定义对字段的自定义验证逻辑。它会在字段赋值时被调用,并可以执行复杂的验证规则。
  • 错误处理:如果验证失败,可以抛出 ValueError 或其他异常类型,Pydantic 会将这些异常作为验证错误报告。

模型继承与嵌套

Pydantic 支持模型继承和嵌套模型,允许在复杂的数据结构中重用和扩展模型定义。

from pydantic import BaseModel

class Address(BaseModel):
    street: str
    city: str

class User(BaseModel):
    id: int
    name: str
    email: str
    address: Address
  • 模型继承:子模型可以继承父模型的字段和验证逻辑。这种继承机制允许重用已有模型并添加额外的字段或逻辑。
  • 嵌套模型:当模型字段是另一个 Pydantic 模型时,Pydantic 会递归地验证嵌套模型中的数据。确保整个数据结构符合预期,并且验证嵌套模型中的字段。

环境变量和配置管理

Pydantic 的 BaseSettings 类用于处理环境变量和配置文件的解析,方便进行配置管理。

from pydantic import BaseSettings

class Settings(BaseSettings):
    db_url: str
    secret_key: str

    class Config:
        env_file = '.env'

settings = Settings()
  • 环境变量解析BaseSettings 类会从环境变量或配置文件中读取配置数据,并将其解析为模型字段。字段名与环境变量名或配置文件中的键匹配。
  • 配置文件:可以通过 Config 类中的 env_file 属性指定配置文件路径。Pydantic 会从指定的文件中加载配置数据,并将其解析为模型字段。

Web 开发中的应用

API 请求和响应模型

在现代 Web 开发中,尤其是使用 FastAPI 这样的框架时,Pydantic 提供了简单而强大的方式来定义和验证 API 请求和响应模型。FastAPI 与 Pydantic 的集成使得数据验证和序列化变得高效且易于实现。

  • 请求体定义:使用 Pydantic 可以定义 API 请求体的结构,包括必填字段和可选字段。Pydantic 会自动进行数据验证,确保请求体的数据符合预期。

    示例:

    from pydantic import BaseModel, EmailStr
    from fastapi import FastAPI, HTTPException
    
    app = FastAPI()
    
    class UserCreate(BaseModel):
        name: str
        email: EmailStr
        age: int
    
    @app.post("/users/")
    def create_user(user: UserCreate):
        return {"name": user.name, "email": user.email, "age": user.age}
    
  • 响应体定义:可以使用 Pydantic 定义 API 的响应体结构,确保返回的数据符合预期格式。

    示例:

    from pydantic import BaseModel
    
    class UserResponse(BaseModel):
        id: int
        name: str
        email: str
    
    @app.get("/users/{user_id}", response_model=UserResponse)
    def read_user(user_id: int):
        # 假设从数据库中获取用户数据
        return {"id": user_id, "name": "John Doe", "email": "[email protected]"}
    

数据验证和转换

在处理 Web 应用中的数据时,Pydantic 可以自动验证和转换数据类型,减少了手动验证的需求,降低了出错的可能性。

  • 数据转换:Pydantic 可以将输入数据自动转换为模型中定义的类型,例如,将字符串转换为整数或浮点数。

    示例:

    class Item(BaseModel):
        id: int
        price: float
    
    item = Item(id="123", price="19.99")  # 自动转换为 int 和 float
    
  • 复杂数据结构验证:对于复杂的嵌套数据结构,Pydantic 提供了强大的支持,能够验证深层次的数据结构。

    示例:

    class Address(BaseModel):
        street: str
        city: str
    
    class User(BaseModel):
        id: int
        name: str
        address: Address
    
    data = {
        "id": 1,
        "name": "John Doe",
        "address": {"street": "123 Main St", "city": "Anytown"}
    }
    user = User(**data)  # 自动验证和解析嵌套结构
    

数据处理中的应用

外部系统数据验证

在处理从外部系统(如 API、数据库等)导入的数据时,Pydantic 可以确保数据的正确性和完整性,避免因数据格式不匹配而导致的问题。

  • 数据导入和验证:使用 Pydantic 对导入的数据进行验证,确保数据符合预期的结构和类型。

    示例:

    from pydantic import BaseModel
    
    class ExternalData(BaseModel):
        id: int
        name: str
        email: str
    
    external_data = {"id": 1, "name": "Jane Doe", "email": "[email protected]"}
    data = ExternalData(**external_data)  # 验证和解析数据
    

数据转换和清洗

Pydantic 还可以用于数据清洗和转换,将外部数据转换为适合内部处理的格式。

  • 数据清洗:通过定义模型,可以确保导入的数据符合一定的标准,例如,将字符串格式的数据转换为日期对象。

    示例:

    from pydantic import BaseModel
    from datetime import datetime
    
    class Event(BaseModel):
        event_date: datetime
    
    data = {"event_date": "2024-08-22T10:00:00"}
    event = Event(**data)  # 自动转换为 datetime 对象
    

Pydantic 的灵活性和强大功能使其在 Web 开发和数据处理场景中成为一个不可或缺的工具,帮助开发者简化数据验证和转换,提高代码的质量和可靠性。

你可能感兴趣的:(python,fastapi,数据库)