Pydantic声明类型信息的库
pydantic enforces type hints at runtime, and provides user friendly errors when data is invalid.
Define how data should be in pure, canonical python; validate it with pydantic.
---
pydantic在运行时强制执行类型提示,并在数据无效时提供用户友好的错误。
定义数据应该如何在纯粹的、规范的 python 中;用pydantic验证它。
注意:pydantic主要是一个解析库,而不是验证库。验证是达到目的的一种手段:建立一个符合所提供的类型和约束的模型。
换句话说,pydantic保证输出模型的类型和约束,而不是输入数据。
from typing import Optional, List
from pydantic import BaseModel
from datetime import datetime
class User(BaseModel):
id: int
name = 'fanjiexiong' # 提供的默认值推断为字符串;因为它有一个默认值,所以它不是必需的。
signup_ts: Optional[datetime] = None
friends: List[int] = []
ex_data = {
'id': '123', #这里是字符串, User是int型请注意
'signup_ts': '2022-01-26 11:26',
'friends': [1, 3, '2']
}
use = User(**ex_data)
print(use.id) #这里能打印出来
print(type(use.id)) #是int型,就是因为使用了pydantic会自动帮你转换 (如果可能,字符串、字节或浮点数将被强制转换为整数;否则将引发异常。)
print(use.dict()) # 转换成字典
use2 = User(id=2, name='tarzan', friends=['1'])
print(use2.id)
print(type(use2.id))
print(use2.dict())
返回结果:
123
<class 'int'>
{'id': 123, 'signup_ts': datetime.datetime(2022, 1, 26, 11, 26), 'friends': [1, 3, 2], 'name': 'fanjiexiong'}
2
<class 'int'>
{'id': 2, 'signup_ts': None, 'friends': [1], 'name': 'tarzan'}
如果验证失败,pydantic 将引发错误并详细说明错误:
from pydantic import ValidationError
try:
User(signup_ts='broken', friends=[1, 2, 'not number'])
except ValidationError as e:
print(e.json())
安装
pip3 install pydantic
基本使用
from pydantic import BaseModel
class User(BaseModel):
id: int
name = 'Jane Doe'
User
这是一个模型,它有两个字段id
整数,name
字符串,name不是必需的(它有一个默认值)。name
是从默认值推断出来的,因此不需要类型注释(但是请注意当某些字段没有类型注释时有关字段顺序的警告)
user = User(id='123')
user
这是一个实例User
。对象的初始化将执行所有解析和验证,如果没有ValidationError
引发,您知道生成的模型实例是有效的。
assert user.id == 123
模型的字段可以作为用户对象的普通属性访问。字符串 '123' 已根据字段类型转换为 int
assert user.name == 'Jane Doe'
name
初始化用户时未设置,因此它具有默认值
assert user.dict() == dict(user) == {'id': 123, 'name': 'Jane Doe'}
.dict()
将dict(user)
提供字段的字典,但.dict()
可以采用许多其他参数。
user.id = 321
assert user.id == 321
此模型是可变的,因此可以更改字段值。
实例化的对象具有的方法
具有以下方法和属性:
dict()
- 返回模型字段和值的字典;
json()
- 返回一个 JSON 字符串表示
dict()
; copy()
- 返回模型的副本(默认为浅拷贝);其实理解成深拷贝也没有问题, 因为List不支持[]语法,只有Tuple支持[],元祖本身就是不可变对象
parse_obj()
- 如果对象不是字典,则用于将任何对象加载到具有错误处理的模型中的实用程序;
parse_raw()
- 用于加载多种格式字符串的实用程序;
parse_file()
- 喜欢
parse_raw()
但是对于文件路径; schema()
- 返回将模型表示为 JSON Schema 的字典;
schema_json()
schema()
返回;的 JSON 字符串表示形式-
递归模型:
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] # bars参数外面是个列表,列表里面是多个Bar模型每一个都是已通过字典封装的 ex = { 'foo': {'count': 1}, "bars": [{ 'apple': 'x1', 'banana': 'y1' }] } s = Spam(**ex) print(s.dict())
ORM 模式
Pydantic 模型可以从任意类实例创建以支持映射到 ORM 对象的模型。
- Config属性
orm_mode
必须设置True
为。 from_orm
必须使用特殊构造函数来创建模型实例。
此处的示例使用 SQLAlchemy,但相同的方法应该适用于任何 ORM。 这里还没有看出来什么时候使用他
from typing import List from sqlalchemy import Column, Integer, String from sqlalchemy.dialects.postgresql import ARRAY from sqlalchemy.ext.declarative import declarative_base from pydantic import BaseModel, constr Base = declarative_base() class CompanyOrm(Base): __tablename__ = 'companies' id = Column(Integer, primary_key=True, nullable=False) public_key = Column(String(20), index=True, nullable=False, unique=True) name = Column(String(63), unique=True) domains = Column(ARRAY(String(255))) class CompanyModel(BaseModel): id: int public_key: constr(max_length=20) name: constr(max_length=63) domains: List[constr(max_length=255)] class Config: orm_mode = True co_orm = CompanyOrm( id=123, public_key='foobar', name='Testing', domains=['example.com', 'foobar.com'], ) print(co_orm) #> <models_orm_mode.CompanyOrm object at 0x7f0bdac44850> co_model = CompanyModel.from_orm(co_orm) print(co_model) #> id=123 public_key='foobar' name='Testing' domains=['example.com', #> 'foobar.com']
- Config属性