0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Pydantic:强大的数据校验工具

科技绿洲 来源:Python实用宝典 作者:Python实用宝典 2023-10-30 11:40 次阅读

Pydantic 是一个使用Python类型注解进行数据验证和管理的模块。安装方法非常简单,打开终端输入:

pip install pydantic

它类似于 Django DRF 序列化器的数据校验功能,不同的是,Django里的序列化器的Field是有限制的,如果你想要使用自己的Field还需要继承并重写它的基类:

# Django 序列化器的一个使用例子,你可以和下面Pydantic的使用作对比
class Book(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    author = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)

而 Pydantic 基于Python3.7以上的类型注解特性,实现了可以对任何类做数据校验的功能:

上滑查看更多代码

# Pydantic 数据校验功能
from datetimeimport datetime
from typingimport List, Optional
from pydanticimport BaseModel


class User(BaseModel):
id: int
name ='John Doe'
signup_ts: Optional[datetime] =None
friends: List[int] = []


external_data = {
'id':'123',
'signup_ts':'2019-06-01 12:22',
'friends': [1,2,'3'],
}
user = User(**external_data)
print(user.id)
print(type(user.id))
# > 123
# > < class 'int' >
print(repr(user.signup_ts))
# > datetime.datetime(2019, 6, 1, 12, 22)
print(user.friends)
# > [1, 2, 3]
print(user.dict())
"""
{
'id': 123,
'signup_ts': datetime.datetime(2019, 6, 1, 12, 22),
'friends': [1, 2, 3],
'name': 'John Doe',
}
"""

从上面的基本使用可以看到,它甚至能自动帮你做数据类型的转换,比如代码中的 user.id, 在字典中是字符串,但经过Pydantic校验器后,它自动变成了int型,因为User类里的注解就是int型。

当我们的数据和定义的注解类型不一致时会报这样的Error:

from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel


class User(BaseModel):
    id: int
    name = 'John Doe'
    signup_ts: Optional[datetime] = None
    friends: List[int] = []


external_data = {
    'id': '123',
    'signup_ts': '2019-06-01 12:222',
    'friends': [1, 2, '3'],
}
user = User(**external_data)
"""
Traceback (most recent call last):
  File "1.py", line 18, in < module >
    user = User(**external_data)
  File "pydanticmain.py", line 331, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for User
signup_ts
  invalid datetime format (type=value_error.datetime)
"""

即 "invalid datetime format", 因为我传入的 signup_ts 不是标准的时间格式(多了个2)。

1. Pydantic模型数据导出 ****

通过Pydantic模型中自带的 json 属性方法,能让经过校验后的数据一行命令直接转成 json 字符串,如前文中的 user 对象:

print(user.dict()) # 转为字典
"""
{
    'id': 123,
    'signup_ts': datetime.datetime(2019, 6, 1, 12, 22),
    'friends': [1, 2, 3],
    'name': 'John Doe',
}
"""
print(user.json()) # 转为json
"""
{"id": 123, "signup_ts": "2019-06-01T12:22:00", "friends": [1, 2, 3], "name": "John Doe"}
"""

非常方便。它还支持将整个数据结构导出为 schema json,它能完整地描述整个对象的数据结构类型:

上滑查看更多代码

print(user.schema_json(indent=2))
"""
{
"title": "User",
"type": "object",
"properties": {
"id": {
"title": "Id",
"type": "integer"
},
"signup_ts": {
"title": "Signup Ts",
"type": "string",
"format": "date-time"
},
"friends": {
"title": "Friends",
"default": [],
"type": "array",
"items": {
"type": "integer"
}
},
"name": {
"title": "Name",
"default": "John Doe",
"type": "string"
}
},
"required": [
"id"
]
}
"""

2.数据导入

除了直接定义数据校验模型,它还能通过ORM、字符串、文件导入到数据校验模型:

比如字符串(raw):

from datetime import datetime
from pydantic import BaseModel


class User(BaseModel):
    id: int
    name = 'John Doe'
    signup_ts: datetime = None
      
m = User.parse_raw('{"id": 123, "name": "James"}')
print(m)
# > id=123 signup_ts=None name='James'

此外,它能直接将ORM的对象输入,转为Pydantic的对象,比如从Sqlalchemy ORM:

上滑查看更多代码

from typingimport List
from sqlalchemyimport Column, Integer, String
from sqlalchemy.dialects.postgresqlimport ARRAY
from sqlalchemy.ext.declarativeimport declarative_base
from pydanticimport 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']

从Json文件导入:

from datetime import datetime
from pathlib import Path
from pydantic import BaseModel


class User(BaseModel):
    id: int
    name = 'John Doe'
    signup_ts: datetime = None
      
path = Path('data.json')
path.write_text('{"id": 123, "name": "James"}')
m = User.parse_file(path)
print(m)

从pickle导入:

import pickle
from datetime import datetime
from pydantic import BaseModel

pickle_data = pickle.dumps({
    'id': 123,
    'name': 'James',
    'signup_ts': datetime(2017, 7, 14)
})
m = User.parse_raw(
    pickle_data, content_type='application/pickle', allow_pickle=True
)
print(m)
# > id=123 signup_ts=datetime.datetime(2017, 7, 14, 0, 0) name='James'

3.自定义数据校验

你还能给它增加 validator 装饰器,增加你需要的校验逻辑:

上滑查看更多代码

from sklearn.metrics import confusion_matrix
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# 1.导入数据集
dataset = pd.read_csv('Social_Network_Ads.csv')
X = dataset.iloc[:, [1, 2, 3]].values
Y = dataset.iloc[:, 4].values

# 性别转化为数字
labelencoder_X = LabelEncoder()
X[:, 0] = labelencoder_X.fit_transform(X[:, 0])

# 2.将数据集分成训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, Y, test_size=0.25, random_state=0)

# 3.特征缩放
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# 4.训练
classifier = LogisticRegression()
classifier.fit(X_train, y_train)

# 5.预测
y_pred = classifier.predict(X_test)

# 6.评估预测

# 生成混淆矩阵
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
print(cm)

上面,我们增加了三种自定义校验逻辑:

1.name 必须带有空格

2.password2 必须和 password1 相同

3.username 必须为字母

让我们试试这三个校验是否有效:

user = UserModel(
    name='samuel colvin',
    username='scolvin',
    password1='zxcvbn',
    password2='zxcvbn',
)
print(user)
# > name='Samuel Colvin' username='scolvin' password1='zxcvbn' password2='zxcvbn'

try:
    UserModel(
        name='samuel',
        username='scolvin',
        password1='zxcvbn',
        password2='zxcvbn2',
    )
except ValidationError as e:
    print(e)
    """
    2 validation errors for UserModel
    name
      must contain a space (type=value_error)
    password2
      passwords do not match (type=value_error)
    """

可以看到,第一个UserModel里的数据完全没有问题,通过校验。

第二个UserModel里的数据,由于name存在空格,password2和password1不一致,无法通过校验。因此我们定义的自定义校验器完全有效。

4.性能表现

这是最令我惊讶的部分,Pydantic 比 Django-rest-framework 的校验器还快了12.3倍:

Package版本相对表现平均耗时
pydantic1.7.393.7μs
attrs + cattrs20.31.5x slower143.6μs
valideer0.4.21.9x slower175.9μs
marshmallow3.102.4x slower227.6μs
voluptuous0.122.7x slower257.5μs
trafaret2.1.03.2x slower296.7μs
schematics2.1.010.2x slower955.5μs
django-rest-framework3.1212.3x slower1148.4μs
cerberus1.3.225.9x slower2427.6μs
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 模块
    +关注

    关注

    7

    文章

    2706

    浏览量

    47472
  • 数据
    +关注

    关注

    8

    文章

    7026

    浏览量

    89034
  • 代码
    +关注

    关注

    30

    文章

    4788

    浏览量

    68607
  • python
    +关注

    关注

    56

    文章

    4797

    浏览量

    84687
收藏 人收藏

    评论

    相关推荐

    实时嵌入式系统模型校验技术

    模型校验是最成功的需求验证工具。模型校验的基本原理如图1所示。模型校验工具的输入是系统需求或设计(称为模型)以及最终系统期望实现的特性(称为
    发表于 11-01 18:14 842次阅读
    实时嵌入式系统模型<b class='flag-5'>校验</b>技术

    基于Atmega128单片机和CRC校验码实现无线传输数据时的差错校验

    随着技术的不断进步,各种数据通信的应用越来越广泛。由于传输距离、现场状况、干扰等诸多因素的影响,设备之间的通信数据常会发生一些无法预测的错误。为了降低错误所带来的影响,一般在通信时采用数据校验
    的头像 发表于 05-05 17:36 3374次阅读
    基于Atmega128单片机和CRC<b class='flag-5'>校验</b>码实现无线传输<b class='flag-5'>数据</b>时的差错<b class='flag-5'>校验</b>

    英飞凌强大的AURIX和工具链简介

    英飞凌强大的AURIX,工具链简介,谢谢北京西能提供工具简介资料,希望对学习Tricore的童鞋有所指引。Aurix开发工具链20131219.pdf (1.03 MB )
    发表于 12-14 10:42

    校验遇到数据校验不到而导致出错

    串口发送数据时,利用和校验的方法对数据进行校验,但是遇到数据校验不到而导致出错,请问这种情况该如
    发表于 04-14 23:04

    CRC校验代码自动生成工具

    CRC校验代码自动生成工具根据输入条件自动产生各种CRC的VHDL或verilog源程序
    发表于 05-20 11:16 294次下载
    CRC<b class='flag-5'>校验</b>代码自动生成<b class='flag-5'>工具</b>

    基于Labview的串口通信数据校验和的实现方法

    基于Labview的串口通信数据校验和的实现方法
    发表于 01-09 17:58 173次下载
    基于Labview的串口通信<b class='flag-5'>数据</b><b class='flag-5'>校验</b>和的实现方法

    校验位的小工具

    电子发烧友网站提供《算校验位的小工具.exe》资料免费下载
    发表于 07-25 16:06 2次下载

    文件校验工具

    支持校验文件的MD5SHA-256等值
    发表于 05-05 08:37 16次下载

    循环冗余校验奇偶校验累加和校验等知识分享

    CRC校验(循环冗余校验)是数据通讯中最常采用的校验方式。在嵌入式软件开发中,经常要用到CRC
    的头像 发表于 11-08 09:31 8737次阅读
    循环冗余<b class='flag-5'>校验</b>奇偶<b class='flag-5'>校验</b>累加和<b class='flag-5'>校验</b>等知识分享

    奇偶校验是什么

    校验依据:判断传输的一组二进制数据中”1”的个数是奇数还是偶数 奇校验:如果以二进制数据中1的个数是奇数为依据,则是奇校验
    发表于 07-31 17:35 4次下载
    奇偶<b class='flag-5'>校验</b>是什么

    数据是如何使VPN成为强大工具

    随着时间的推移,大数据已经使VPN成为强大的隐私工具。而即使到现在,这种情况仍在持续。
    发表于 03-12 15:22 1252次阅读

    单片机通信数据校验

    单片机通信数据校验
    发表于 11-23 17:36 33次下载
    单片机通信<b class='flag-5'>数据</b><b class='flag-5'>校验</b>

    工控常用LRC XOR累加和CRC校验工具校验码自动生成软件多计算方式

    CRC校验工具 校验码自动生成软件支持十几种CRC计算方式,包括MODBUS协议的CRC-16校验,CRC4、CRC5、CRC6、CRC7、CRC8、CRC16等21种算法,见图示。两
    的头像 发表于 11-25 14:27 3473次阅读
    工控常用LRC XOR累加和CRC<b class='flag-5'>校验</b><b class='flag-5'>工具</b><b class='flag-5'>校验</b>码自动生成软件多计算方式

    什么是奇校验和偶校验?常见的奇偶校验方式有哪些?

    什么是奇校验和偶校验?常见的奇偶校验方式有哪些? 1. 奇偶校验是指在数字通信中采用一种技术对传输的数据进行
    的头像 发表于 10-17 16:28 1w次阅读

    奇偶校验和crc校验的区别 CRC校验和奇偶校验之间有什么关系?

    奇偶校验和crc校验的区别 CRC校验和奇偶校验之间有什么关系? 奇偶校验和 CRC(Cyclic Redundancy Check)
    的头像 发表于 10-17 16:28 3406次阅读