Pydantic 不是数据清洗工具,而是通过 BaseModel 提供强类型校验与自动转换,在清洗前拦截脏数据;支持递归验证、字段约束、自定义校验器及清洗后可信输出。

Pydantic 不是数据清洗工具,但它能让你在清洗前就拦住脏数据——类型校验不是附加功能,而是清洗流程的第一道过滤网。
为什么 BaseModel 比手动 isinstance() 更可靠?
手动检查类型容易漏掉嵌套结构、空值容忍、字符串转数字等边界情况;BaseModel 默认做递归验证、自动类型转换(比如把 "123" 转成 int),还支持字段级约束。
- 字段声明即校验规则:
age: int会拒绝None、"abc"、3.14 - 空字符串
""对str字段合法,但对constr(min_length=1)不合法 -
Optional[str]允许None或字符串,但不会把0或False当成空字符串自动转 - 错误信息自带路径:
1 validation error for User age type=int_type, input_value='xxx', input_type=str
清洗前用 model_validate() 做强约束校验
别在清洗逻辑里反复写 if not isinstance(...),把原始字典丢给模型,让它一次性报错或转成干净对象。
- 用
model_validate()(v2 推荐)替代已弃用的parse_obj() - 传入字典时,字段名必须完全匹配,多余字段默认被忽略(除非设
model_config = ConfigDict(extra='forbid')) - 想允许部分字段缺失?用
Field(default=None)或Optional[int],但注意:默认值None不等于“可为空”,它只是缺省值 - 示例:
from pydantic import BaseModel, Field <p>class Order(BaseModel): id: int amount: float status: str = Field(default="pending", pattern=r"^(pending|shipped|delivered)$")</p><p>try: Order.model_validate({"id": "100", "amount": "99.9", "status": "shipped"}) except Exception as e: print(e) # 成功:自动转 int/float,且 status 合法</p>
清洗过程中用 @field_validator 做业务逻辑校验
类型正确 ≠ 数据合理。手机号长度、邮箱格式、日期范围这些,得靠自定义校验器。
-
@field_validator('phone')只作用于单个字段,接收原始值,返回清洗后值(比如统一去空格、补区号) - 用
self.instance访问其他字段?不行——field_validator是静态上下文,跨字段逻辑用@model_validator(mode='after') - 抛异常要用
raise ValueError("..."),Pydantic 会捕获并整合进统一错误 - 避免在 validator 里调外部 API 或 IO 操作——它应是纯函数,否则影响性能和可测试性
model_dump() 输出的是清洗后的可信数据,不是原始输入
经过 model_validate() 和 validator 处理后,model_dump() 返回的字典已是类型安全、格式规范、业务合规的结果——这才是你该交给下游(数据库、API、分析模块)的数据。
- 默认不输出
None字段,加exclude_none=True显式控制 - 时间字段自动转 ISO 格式字符串,不需要额外
strftime - 如果清洗后还要改字段(比如加计算字段),建议用
@computed_field,而不是直接改dict - 注意:
model_dump(mode='json')会序列化为 JSON 兼容类型(如datetime→str),但不会做额外校验
真正难的不是写 validator,而是决定哪些规则该放模型里、哪些该放清洗函数里。比如“订单金额不能为负”适合放模型,“同一用户 24 小时内下单不超过 5 次”就得查数据库——后者不属于 Pydantic 的职责边界。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











