使用Pydantic在Python中解析和验证数据

2023年 7月 11日 52.6k 0

Pydantic 简单介绍

通过pydantic库,我们可以更为规范地定义和使用数据接口,这对于大型项目的开发将会更为友好。

❝Pydantic is the most widely used data validation library for Python.

With Pydantic, Python type annotations become more than tools for documentation and type checking. Pydantic 「enforces type hints」 at runtime, and provides 「user-friendly errors」 when data is invalid.

Pydantic is simple to use, even when doing complex things, and enables you to define and validate data in pure, canonical Python.

Pydantic是Python中使用最广泛的数据验证库。

有了Pydantic,Python类型注释不仅仅是用于文档和类型检查的工具。Pydantic在运行时强制执行类型提示,并在数据无效时提供用户友好的提示。

Pydantic使用起来很简单,即使在做复杂的事情时也是如此,它使您能够用简洁,规范的Python定义和验证数据。

使用Pydantic在Python中解析和验证数据

安装使用

pip install pydantic

注意事项

pydantic是一个解析库,而不是一个验证库。如果您不确定这意味着什么,或许它可能如何影响您的使用。

❝pydantic is primarily a parsing library, 「not a validation library」. Validation is a means to an end: building a model which conforms to the types and constraints provided.

In other words, pydantic guarantees the types and constraints of the output model, not the input data.

This might sound like an esoteric distinction, but it is not. If you're unsure what this means or how it might affect your usage you should read the section about Data Conversion below.

Although validation is not the main purpose of pydantic, you 「can」 use this library for custom validation.

Models

Basic model usage

pydantic库的数据定义方式是通过BaseModel类来进行定义的,所有基于pydantic的数据类型本质上都是一个BaseModel类。

举个例子

# 2023/5/14 17:23 , @File: test_1.py, @Comment : python3.9.7
from pydantic import BaseModel


class User(BaseModel):
    id: int
    name = "xiaoming"


# id 是必传的
# name 有默认值,非必传
# 基本的实例化方法
user = User(id="123")

print("the user is {}".format(user))
print("the user is {}".format(user.json()))

# the user is id=123 name='xiaoming'
# the user is {"id": 123, "name": "xiaoming"}

assert user.id == 123
assert user.name == "xiaoming"
assert isinstance(user.id, int)

# assert isinstance(user.name, int)
#     assert isinstance(user.name, int)
# AssertionError

# user2 = User(name="xiaohong")
# pydantic.error_wrappers.ValidationError: 1 validation error for User
# id  field required (type=value_error.missing)

再来看看 它都有些什么属性或方法

❝1、type(object),返回对象object的类型

2、dir(object),返回object所有有效的属性列表

3、object.__dict__,返回object对象的__dict__属性,有些对象可能没有__dict__属性

user2= User(id="345",name="dalong")

print(user2.__fields_set__)

print(type(user2))
print(dir(user2))

# {'name', 'id'}
# {'id': 345, 'name': 'dalong'}
# 
# ['Config', '__abstractmethods__', '__annotations__', '__class__', '__class_vars__', '__config__', '__custom_root_type__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__exclude_fields__', '__fields__', '__fields_set__', '__format__', '__ge__', '__get_validators__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__include_fields__', '__init__', '__init_subclass__', '__iter__', '__json_encoder__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__post_root_validators__', '__pre_root_validators__', '__pretty__', '__private_attributes__', '__reduce__', '__reduce_ex__', '__repr__', '__repr_args__', '__repr_name__', '__repr_str__', '__rich_repr__', '__schema_cache__', '__setattr__', '__setstate__', '__signature__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__try_update_forward_refs__', '__validators__', '_abc_impl', '_calculate_keys', '_copy_and_set_values', '_decompose_class', '_enforce_dict_if_root', '_get_value', '_init_private_attributes', '_iter', 'construct', 'copy', 'dict', 'from_orm', 'id', 'json', 'name', 'parse_file', 'parse_obj', 'parse_raw', 'schema', 'schema_json', 'update_forward_refs', 'validate']

使用Pydantic在Python中解析和验证数据

常用Model properties

知道这个,即使你写代码的时候不使用类似的类型注释/注解,看别人代码的时候也会有所帮助,比如下面这些。之前看人写代码的返回值是xxx.schema_json()就有点疑惑,现在总算明白了。

dict() 返回模型字段和值,字典格式
json() 返回模型字段和值,json 字符串格式
schema() 以 JSON Schema 形式返回模型,字典格式
schema_json() 以 JSON Schema 形式返回模型,json 字符串格式
__fields_set__ 该变量返回用户初始化对象时提供了什么字段

Recursive Models

❝可以使用模型本身作为注释中的类型来定义更复杂的分层数据结构。

from typing import Optional
from pydantic import BaseModel


class Foo(BaseModel):
    count: int
    size: Optional[float] = None


class Bar(BaseModel):
    apple = 'x'
    banana = 'y'


class Spam(BaseModel):
    foo: Foo
    bars: list[Bar]


m = Spam(foo={'count': 4}, bars=[{'apple': 'x1'}, {'apple': 'x2'}])
print(m)
#> foo=Foo(count=4, size=None) bars=[Bar(apple='x1', banana='y'),
#> Bar(apple='x2', banana='y')]
print(m.dict())
"""
{
    'foo': {'count': 4, 'size': None},
    'bars': [
        {'apple': 'x1', 'banana': 'y'},
        {'apple': 'x2', 'banana': 'y'},
    ],
}
"""

使用Pydantic在Python中解析和验证数据

剩下还有蛮多内容,这里不再赘述,因为我也没用过,等以后再来分享。接下来看下常用的Field Types,这个对于我们阅读和编写代码很有帮助。

Field 「Types」

基础数据结构

这个对于大家来说应该都好理解。

from pydantic import BaseModel
from typing import Dict, List, Sequence, Set, Tuple

class Demo(BaseModel):
    a: int # 整型
    b: float # 浮点型
    c: str # 字符串
    d: bool # 布尔型
    e: List[int] # 整型列表
    f: Dict[str, int] # 字典型,key为str,value为int
    g: Set[int] # 集合
    h: Tuple[str, int] # 元组

高级数据结构

「介绍几个我之前在别人代码里看到,但不是很懂的吧。Pydantic的内容还蛮多的,确实得用起来才行了。」

Optional :可选类型

如果一个数据类型不是必须的,可以允许用户在使用中不进行传入,则我们可以使用typing库中的Optional方法进行实现。

# 官网给的例子
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': '2017-06-01 12:22', 'friends': [1, '2', b'3']}
user = User(**external_data)
print(user)
#> User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
#> 123
# 2023/5/14 20:54 , @File: test_3.py, @Comment : python3.9.7
from typing import Optional
from pydantic import BaseModel


class Person(BaseModel):
    name: str
    age: Optional[int]


prson = Person(name='John')

print(prson.name)
# 当没有值传入的时候为None
print(prson.age)

# John
# None

Union:允许多种数据类型

如果一个数据可以允许多种数据类型,我们可以通过typing库中的Union方法进行实现。

# 2023/5/14 21:01 , @File: test_4.py, @Comment : python3.9.7
from typing import Union
from pydantic import BaseModel


class Time(BaseModel):
    time: Union[int, str]


# time 既可以是int类型也可以是str类型
time1 = Time(time=12345)
print(time1.json())
time2 = Time(time="2023-7-29")
print(time2.json())

数据默认值的设置

# 2023/5/14 21:05 , @File: test_5.py, @Comment : python3.9.7
# 数据默认值的设置
from pydantic import BaseModel


class Person(BaseModel):
    name: str
    id: int =18
    gender: str = "man"


person = Person(name="Tom")

print(person.json())
# {"name": "Tom", "id": 18, "gender": "man"}

参考资料

下面是我学习时候看到的一些资料,看完能了解个七七八八了。

序号 文章链接 备注
1 https://www.cnblogs.com/poloyy/p/15158713.html 入门系列
2 https://docs.pydantic.dev/1.10/ 官方文档
3 https://cloud.tencent.com/developer/article/1806545 数据类型的介绍
4 https://blog.csdn.net/swinfans/article/details/89629641 写的很全
5 https://github.com/pydantic/pydantic 官方仓库

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论