一、简介
pydantic 库是 python 中用于数据接口定义检查与设置管理的库。
pydantic 在运行时强制执行类型提示,并在数据无效时提供友好的错误。
它具有如下优点:
- 与 IDE/linter 完美搭配,不需要学习新的模式,只是使用类型注解定义类的实例
- 多用途,BaseSettings 既可以验证请求数据,也可以从环境变量中读取系统设置
- 快速
- 可以验证复杂结构
- 可扩展,可以使用validator装饰器装饰的模型上的方法来扩展验证
- 数据类集成,除了BaseModel,pydantic还提供了一个dataclass装饰器,它创建带有输入数据解析和验证的普通 Python 数据类。
二、安装
pip install pydantic
要测试 pydantic 是否已编译,请运行:
import pydantic
print('compiled:', pydantic.compiled)
支持使用dotenv文件获取配置,需要安装 python-dotenv
pip install pydantic[dotenv]
三、常见模型
pydantic中定义对象都是通过模型的,你可以认为模型就是类型语言中的类型。
1、BaseModel 基本模型
from pydantic import BaseModel
class User(BaseModel):
id: int
name = 'Jane Doe
上面的例子,定义了一个User模型,继承自BaseModel,有2个字段,id是一个整数并且是必需的,name是一个带有默认值的字符串并且不是必需的
实例化使用:
user = User(id='123')
实例化将执行所有解析和验证,如果有错误则会触发 ValidationError 报错。
模型具有以下属性:
- dict() 模型字段和值的字典
- json() JSON 字符串表示dict()
- copy() 模型的副本(默认为浅表副本)
- parse_obj() 使用dict解析数据
- parse_raw 将str或bytes并将其解析为json,然后将结果传递给parse_obj
- parse_file 文件路径,读取文件并将内容传递给parse_raw。如果content_type省略,则从文件的扩展名推断
- from_orm() 从ORM 对象创建模型
- schema() 返回模式的字典
- schema_json() 返回该字典的 JSON 字符串表示
- construct() 允许在没有验证的情况下创建模型
- fields_set 初始化模型实例时设置的字段名称集
- fields 模型字段的字典
- config 模型的配置类
2、递归模型
可以使用模型本身作为注释中的类型来定义更复杂的数据结构。
from typing import List
from pydantic import BaseModel
class Foo(BaseModel):
count: int
size: float = None
class Bar(BaseModel):
apple = 'x'
banana = 'y'
class Spam(BaseModel):
foo: Foo
bars: List[Bar]
3、GenericModel 通用模型(泛型):
使用 typing.TypeVar 的实例作为参数,传递给 typing.Generic,然后在继承了pydantic.generics.GenericModel 的模型中使用:
from typing import Generic, TypeVar, Optional, List
from pydantic import BaseModel, validator, ValidationError
from pydantic.generics import GenericModel
DataT = TypeVar('DataT')
class Error(BaseModel):
code: int
message: str
class DataModel(BaseModel):
numbers: List[int]
people: List[str]
class Response(GenericModel, Generic[DataT]):
data: Optional[DataT]
error: Optional[Error]
@validator('error', always=True)
def check_consistency(cls, v, values):
if v is not None and values['data'] is not None:
raise ValueError('must not provide both data and error')
if v is None and values.get('data') is None:
raise ValueError('must provide data or error')
return v
data = DataModel(numbers=[1, 2, 3], people=[])
error = Error(code=404, message='Not found')
print(Response[int](data=1))
#> data=1 error=None
print(Response[str](data='value'))
#> data='value' error=None
print(Response[str](data='value').dict())
#> {'data': 'value', 'error': None}
print(Response[DataModel](data=data).dict())
"""
{
'data': {'numbers': [1, 2, 3], 'people': []},
'error': None,
}
"""
print(Response[DataModel](error=error).dict())
"""
{
'data': None,
'error': {'code': 404, 'message': 'Not found'},
}
"""
try:
Response[int](data='value')
except ValidationError as e:
print(e)
"