Python数据校验核心是“早发现、早报错、易维护”,推荐用pydantic做声明式验证,其次可选dataclasses+__post_init__、函数装饰器或环境变量显式断言。

Python做数据校验,核心是“早发现、早报错、易维护”——不是等到入库或计算时才暴露问题,而是在函数入口、API接收、配置加载等关键节点就拦截非法输入。
用类型提示 + pydantic 做声明式验证
这是目前最主流、最推荐的方式,尤其适合Web API(FastAPI/Starlette)和配置解析场景。它把校验逻辑从代码中抽离为模型定义,清晰且可复用。
- 安装:pip install pydantic
- 定义模型时直接声明字段类型、约束(如最小值、长度、正则、必填)
- 传入数据后调用 model_validate() 或自动触发(如FastAPI参数),失败抛出 ValidationError,含精准错误路径和原因
示例:
from pydantic import BaseModel, Field, field_validator
from typing import List
<p>class User(BaseModel):
name: str = Field(min_length=2, max_length=20)
age: int = Field(ge=0, le=150)
tags: List[str] = Field(default=[])</p><pre class="brush:php;toolbar:false;">@field_validator('name')
def name_must_not_contain_space(cls, v):
if ' ' in v:
raise ValueError('name must not contain space')
return v自动校验
try: user = User(name="Alice", age=25) except ValidationError as e: print(e) # 输出结构化错误信息
轻量场景:用 dataclasses + 自定义 __post_init__
适合内部工具、脚本或不想引入新依赖时。利用 Python 内置 dataclass,在实例化后立即检查。
立即学习“Python免费学习笔记(深入)”;
- 用 @dataclass 定义结构
- 在 __post_init__ 中写校验逻辑,不满足则 raise ValueError
- 注意:不会自动类型转换,类型错误需靠 IDE 或运行时捕获
示例:
from dataclasses import dataclass
<p>@dataclass
class Config:
host: str
port: int
timeout: float</p><pre class="brush:php;toolbar:false;">def __post_init__(self):
if not isinstance(self.host, str) or not self.host.strip():
raise ValueError("host must be a non-empty string")
if not (0 < self.port <= 65535):
raise ValueError("port must be between 1 and 65535")
if self.timeout <= 0:
raise ValueError("timeout must be positive")
函数级校验:用装饰器封装通用规则
当多个函数需要类似校验(如“所有字符串参数非空”“数值参数 > 0”),可写一个校验装饰器,避免重复代码。
- 装饰器接收校验规则(如参数名→校验函数映射)
- 调用前遍历参数,对匹配字段执行校验函数
- 校验失败统一 raise TypeError 或自定义异常
示例(简化版):
def validate(**rules):
def decorator(func):
def wrapper(*args, **kwargs):
sig = inspect.signature(func)
bound = sig.bind(*args, **kwargs)
bound.apply_defaults()
for param, checker in rules.items():
value = bound.arguments.get(param)
if not checker(value):
raise ValueError(f"Invalid {param}: {value}")
return func(*args, **kwargs)
return wrapper
return decorator
<p>@validate(username=lambda x: isinstance(x, str) and len(x) >= 3)
def create_user(username):
return f"User {username} created"
配置/环境变量校验:结合 os.getenv + 显式断言
读取环境变量或配置文件时,常遇到缺失、类型错、格式错等问题。不要默认信任字符串,要主动转、主动查。
- 用 os.getenv() 获取后,立刻检查是否为 None 或空字符串
- 尝试转换(如 int(os.getenv("PORT"))),捕获 ValueError
- 对关键配置(如数据库URL、密钥)加存在性 + 格式双重校验(可用正则或 urlparse)
示例:
import os
from urllib.parse import urlparse
<p>db_url = os.getenv("DATABASE_URL")
if not db_url:
raise RuntimeError("DATABASE_URL is required")</p><p>parsed = urlparse(db_url)
if parsed.scheme not in ("postgresql", "sqlite"):
raise ValueError(f"Unsupported database scheme: {parsed.scheme}")


















