• 微信:WANCOME
  • 扫码加微信,提供专业咨询
  • 服务热线
  • 13215191218
    13027920428

  • 微信扫码访问本页
desc-2
环企首页

Pydantic 详解

Pydantic 是 Python 中最流行的数据验证和设置管理库,它利用 Python 类型注解在运行时对数据进行验证,并提供清晰的错误信息。

1. 核心概念

  • 数据验证:自动检查数据是否符合指定的类型和约束
  • 类型转换:尽可能将输入数据转换为正确的类型
  • 序列化:轻松将模型转换为字典或 JSON 格式
  • IDE 友好:基于类型注解,提供完美的代码补全和支持

2. 基础用法

最简单的例子

from pydantic import BaseModel class User(BaseModel): name: str age: int email: str # 自动验证和类型转换 user = User(name="张三", age="25", email="zhang@example.com") print(user) # name='张三' age=25 email='zhang@example.com' print(user.age + 1) # 26 (被正确转换为 int) # 无效数据会引发错误 try: user2 = User(name="李四", age="not a number", email="li@example.com") except ValidationError as e: print(e)

字段的默认值和可选字段

from pydantic import BaseModel from typing import Optional class Config(BaseModel): name: str = "默认配置" # 默认值 debug: bool = False # 默认 False timeout: Optional[int] = None # 可选字段,默认 None tags: list[str] = [] # 空列表作为默认值 config = Config() print(config.name) # "默认配置" print(config.debug) # False config2 = Config(name="自定义", debug=True) print(config2.name) # "自定义"

3. 高级验证

使用 Field 添加验证规则

from pydantic import BaseModel, Field, ValidationError from typing import Optional class Product(BaseModel): name: str = Field(..., min_length=1, max_length=100) # ... 表示必填 price: float = Field(..., gt=0, le=9999.99) # 大于0,小于等于9999.99 quantity: int = Field(default=0, ge=0) # 大于等于0 description: Optional[str] = Field(None, max_length=500) try: product = Product(name="", price=-10) # 验证失败 except ValidationError as e: print(e.errors())

自定义验证器

from pydantic import BaseModel, field_validator, model_validator class Order(BaseModel): items: list[str] quantities: list[int] discount: float = 0.0 # 单个字段验证 @field_validator('discount') @classmethod def validate_discount(cls, v: float) -> float: if not 0 <= v <= 1: raise ValueError('折扣必须在0-1之间') return v # 多个字段验证 @model_validator(mode='after') def check_lengths(self) -> 'Order': if len(self.items) != len(self.quantities): raise ValueError('商品列表和数量列表长度必须相同') return self order = Order(items=["book"], quantities=[2, 3]) # 长度不匹配 -> 报错

使用 ConfigDict 配置模型行为

from pydantic import BaseModel, ConfigDict class User(BaseModel): model_config = ConfigDict( extra='forbid', # 禁止额外字段 frozen=True, # 不可变对象 title='UserModel' # 模型标题 ) user = User(name="张三") # user.name = "李四" # 如果 frozen=True,这会报错

4. 嵌套模型

from pydantic import BaseModel from typing import List class Address(BaseModel): street: str city: str zipcode: str class User(BaseModel): name: str age: int address: Address # 嵌套模型 tags: List[str] = [] # 列表类型 # 可以传字典,Pydantic 会自动转换 user_data = { "name": "张三", "age": 25, "address": { "street": "中关村大街1号", "city": "北京", "zipcode": "100080" }, "tags": ["developer", "python"] } user = User(**user_data) print(user.address.city) # 北京

5. 序列化和反序列化

from pydantic import BaseModel from datetime import datetime class Event(BaseModel): name: str timestamp: datetime event = Event(name="会议", timestamp="2024-01-15T10:30:00") # 转换为字典 event_dict = event.model_dump() print(event_dict) # {'name': '会议', 'timestamp': datetime.datetime(2024, 1, 15, 10, 30)} # 转换为 JSON event_json = event.model_dump_json() print(event_json) # {"name":"会议","timestamp":"2024-01-15T10:30:00"} # 从字典反序列化 event2 = Event.model_validate(event_dict) # 从 JSON 反序列化 event3 = Event.model_validate_json(event_json)

6. 在 LangGraph 中的实际应用

你在 LangGraph 中可能会看到这样的用法:

from typing import Annotated, List from langgraph.graph.message import add_messages from pydantic import BaseModel # 定义状态模型 class MessagesState(BaseModel): messages: Annotated[List[AnyMessage], add_messages] user_name: str = "anonymous" session_id: str = "" # 可以添加验证规则 current_step: str = Field(default="start", pattern="^(start|process|end)$") # 使用模型 state = MessagesState( messages=[HumanMessage(content="你好")], session_id="session_123" ) print(state.current_step) # "start"

7. 常用 Field 参数

参数 说明 示例
default 默认值 Field(default=0)
... (Ellipsis) 必填字段 Field(...)
gt 大于 Field(gt=0)
ge 大于等于 Field(ge=0)
lt 小于 Field(lt=100)
le 小于等于 Field(le=100)
min_length 最小长度 Field(min_length=1)
max_length 最大长度 Field(max_length=100)
pattern 正则表达式 Field(pattern=r'^[A-Z]+$')
description 字段描述 Field(description="用户名")

8. 性能优化:使用 @dataclass 装饰器

对于简单场景,可以使用性能更好的 @dataclass 装饰器:

from pydantic.dataclasses import dataclass @dataclass class Point: x: float y: float @field_validator('x') @classmethod def validate_x(cls, v: float) -> float: if v < 0: raise ValueError('x 不能为负数') return v point = Point(x=10, y=20)

9. 与类型注解配合

from typing import Union, Literal, Optional from datetime import date class Task(BaseModel): id: int title: str status: Literal['pending', 'in_progress', 'completed'] # 字面量类型 due_date: Union[date, None] = None # 联合类型 priority: Optional[int] = None # 可选类型

10. Pydantic vs 普通类

特性 普通 Python 类 Pydantic 模型
类型检查 ❌ 不在运行时检查 ✅ 自动验证
类型转换 ❌ 手动处理 ✅ 自动转换
序列化 ❌ 需要手动实现 ✅ 内置方法
验证规则 ❌ 手动写 if ✅ 声明式
JSON 支持 ❌ 需要库 ✅ 原生支持
性能 较快 略慢(含验证开销)

💎 总结

  • Pydantic 的核心价值:利用 Python 类型注解,在运行时提供数据验证和类型转换
  • 主要使用场景:配置管理、API 请求/响应验证、数据序列化、LangGraph 状态管理
  • 最佳实践:始终为关键数据模型使用 Pydantic,利用内置验证器而非手动写 if 语句
  • 版本注意:Pydantic v2 与 v1 有较大变化,你当前使用的是 v2(从语法看)

如果你使用 LangGraph,Pydantic 帮助你确保状态模型的一致性和安全性,特别是在复杂的 Agent 工作流中。