python中pydantic库

2023-11-03

pydantic库详解

一、 概述

1、 简介

该库的官方文档位置为:https://pydantic-docs.helpmanual.io/

不知道大家是否非常羡慕C语言等在进行函数传参时,可以指定数据类型来传参呢?

我之前有一篇讲过使用typing来指定数据类型,但是其仅仅是能指定数据类型,只能做一个提醒的作用,那么我们如何来结合typing模块,来写一个可以像Java等语言的指定参数类型呢?这里我推荐pydantic库。

首先,在学这个库之前,我们需要去回顾一下typing库的使用方法:https://blog.csdn.net/qq_62789540/article/details/124790174

然后,我们来解释一下我们即将要学的库:

其使用 Python 类型注释的数据验证和设置管理。

pydantic在运行时强制执行类型提示,并在数据无效时提供用户友好的错误。

定义数据应该如何在纯的、规范的 Python 中保存;用pydantic验证它。

2、 优势

所以pydantic使用了一些很酷的新语言特性,但我为什么要实际去使用它呢?

  • 与您的 IDE/linter/brain 配合得很好

    无需学习新的模式定义微语言。如果你知道如何使用 Python 类型提示,你就会知道如何使用pydantic。数据结构只是您使用类型注释定义的类的实例,因此自动完成、linting、mypy、IDE(尤其是PyCharm)和您的直觉都应该与您的验证数据正常工作。

  • 两用

    pydantic 的 BaseSettings类允许在“验证此请求数据”上下文和“加载我的系统设置”上下文中使用*pydantic 。*主要区别在于系统设置可以从环境变量中读取,并且通常需要更复杂的对象,例如 DSN 和 Python 对象。

  • 快速地

    pydantic一直非常重视性能,大多数库都是用 cython 编译的,加速了约 50%,它通常与大多数类似库一样快或更快。

  • 验证复杂结构

    使用递归pydantic模型typing标准类型(例如ListTupleDict)和 验证器允许清晰、轻松地定义、验证和解析复杂的数据模式。

  • 可扩展

    pydantic允许定义自定义数据类型,或者您可以使用validator装饰器装饰的模型上的方法扩展验证。

  • 数据类集成

    以及BaseModelpydantic提供了一个dataclass装饰器,它创建(几乎)带有输入数据解析和验证的普通 Python 数据类。

3、 环境配置

安装这个库的方法非常简单:

pip install pydantic

安装配置的扩展功能:

pip install pydantic[email]  # 邮箱验证支持
# or
pip install pydantic[dotenv]  # dotenv文件支持
# or just
pip install pydantic[email, dotenv]  # 同时安装

如果想要通过其他方式安装,可以参考官方文档

二、 Model

1、 模型属性

在pydantic中定义对象的主要方法是通过模型(模型只是继承自 的类BaseModel)。

您可以将模型视为类似于严格类型语言中的类型,或者视为 API 中单个端点的要求。

不受信任的数据可以传递给模型,并且在解析和验证之后,pydantic保证生成的模型实例的字段将符合模型上定义的字段类型。

属性 描述
dict() 返回模型字段和值的字典
json() 返回一个JSON字符串表示dict()
copy() 返回模型的副本,浅拷贝
parse_obj() 如果对象不是字典,则用于将任何对象加载到具有错误处理的模型中的实用程序
parse_raw() 用于加载多种格式字符串的实用程序
from_orm() 将数据从任意类加载到模型中
schema() 返回将模型表示为JSON Schema的字典
schema_json() 返回schema()的JSON字符串表示形式
construct() 无需运行验证即可创建模型的类方法
__fields_set__ 初始化模型实例时设置字段名称集
__fields__ 模型字段的字典
__config__ 模型的配置类

2、 基本使用

from pydantic import BaseModel


class Foo(BaseModel):
    count: int
    size: float | None = 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'},
    ],
}
"""

3、数据导入

3.1 orm

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_3_9.CompanyOrm object at 0x7fb20cc17790>
co_model = CompanyModel.from_orm(co_orm)
print(co_model)
#> id=123 public_key='foobar' name='Testing' domains=['example.com',
#> 'foobar.com']

3.2 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.3 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)

4、 数据导出

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"
  ]
}
"""

三、 验证器

1、 类内添加

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

from pydantic import BaseModel, ValidationError, validator


class UserModel(BaseModel):
    name: str
    username: str
    password1: str
    password2: str

    @validator('name')
    def name_must_contain_space(cls, v):
        if ' ' not in v:
            raise ValueError('must contain a space')
        return v.title()

    @validator('password2')
    def passwords_match(cls, v, values, **kwargs):
        if 'password1' in values and v != values['password1']:
            raise ValueError('passwords do not match')
        return v

    @validator('username')
    def username_alphanumeric(cls, v):
        assert v.isalnum(), 'must be alphanumeric'
        return v


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)
    """

2、 重用验证器

有时,您会希望在多个字段/模型上使用相同的验证器(例如,规范化某些输入数据)。方法是编写一个单独的函数,然后从多个装饰器中调用它。显然,这需要大量重复和样板代码。为了避免这种情况,在v1.2allow_reuse中添加了该参数 (默认情况下)

from pydantic import BaseModel, validator


def normalize(name: str) -> str:
    return ' '.join((word.capitalize()) for word in name.split(' '))


class Producer(BaseModel):
    name: str

    # validators
    _normalize_name = validator('name', allow_reuse=True)(normalize)


class Consumer(BaseModel):
    name: str

    # validators
    _normalize_name = validator('name', allow_reuse=True)(normalize)


jane_doe = Producer(name='JaNe DOE')
john_doe = Consumer(name='joHN dOe')
assert jane_doe.name == 'Jane Doe'
assert john_doe.name == 'John Doe'

3、 根验证器

from pydantic import BaseModel, ValidationError, root_validator


class UserModel(BaseModel):
    username: str
    password1: str
    password2: str

    @root_validator(pre=True)
    def check_card_number_omitted(cls, values):
        assert 'card_number' not in values, 'card_number should not be included'
        return values

    @root_validator
    def check_passwords_match(cls, values):
        pw1, pw2 = values.get('password1'), values.get('password2')
        if pw1 is not None and pw2 is not None and pw1 != pw2:
            raise ValueError('passwords do not match')
        return values


print(UserModel(username='scolvin', password1='zxcvbn', password2='zxcvbn'))
#> username='scolvin' password1='zxcvbn' password2='zxcvbn'
try:
    UserModel(username='scolvin', password1='zxcvbn', password2='zxcvbn2')
except ValidationError as e:
    print(e)
    """
    1 validation error for UserModel
    __root__
      passwords do not match (type=value_error)
    """

try:
    UserModel(
        username='scolvin',
        password1='zxcvbn',
        password2='zxcvbn',
        card_number='1234',
    )
except ValidationError as e:
    print(e)
    """
    1 validation error for UserModel
    __root__
      card_number should not be included (type=assertion_error)
    """

与字段验证器一样,根验证器可以具有pre=True,在这种情况下,在字段验证发生之前调用它们(并提供原始输入数据),或者pre=False(默认),在这种情况下,在字段验证之后调用它们。

pre=True如果根验证器引发错误,则不会发生字段验证。与字段验证器一样,pre=False即使先前的验证器失败,也会默认调用“post”(即)根验证器;skip_on_failure=True可以通过将关键字参数设置为验证器来更改此行为。该values参数将是一个字典,其中包含通过字段验证的值和适用的字段默认值。

4、 验证装饰器

validate_arguments装饰器允许在调用函数之前使用函数的注释解析和验证传递给函数的参数。在引擎盖下,它使用相同的模型创建和初始化方法;它提供了一种非常简单的方法,可以用最少的样板对代码应用验证。

import os
from pathlib import Path
from typing import Pattern, Optional

from pydantic import validate_arguments, DirectoryPath


@validate_arguments
def find_file(path: DirectoryPath, regex: Pattern, max=None) -> Optional[Path]:
    for i, f in enumerate(path.glob('**/*')):
        if max and i > max:
            return
        if f.is_file() and regex.fullmatch(str(f.relative_to(path))):
            return f


# note: this_dir is a string here
this_dir = os.path.dirname(__file__)

print(find_file(this_dir, '^validation.*'))
#> /home/runner/work/pydantic/pydantic/docs/examples/validation_decorator_async.
#> py
print(find_file(this_dir, '^foobar.*', max=3))
#> None

几点注意事项:

  • 尽管它们作为字符串传递,path并由装饰器分别regex转换为对象和正则表达式Path
  • max没有类型注释,所以会被装饰器认为是Any

这些是常用的方法,想要了解更详细的内容,可以去阅读官方文档:https://pydantic-docs.helpmanual.io/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python中pydantic库 的相关文章

随机推荐

  • 20230705

  • python将生成的数据按类别以不同颜色作散点图

    遇事不决 可问春风 春风不语 即随本心 文章目录 文章目录 前言 一 实例 1 读取数据 2 创建空数组 3 数据处理 4 绘制散点图 总结 前言 我们在处理分类问题时 经常需要用图表的形式将数据表现出来 这样会更直观的了解分类效果 一 实
  • nodejs的加密方式

    nodejs的加密方式 一 加密算法 为了保证数据的安全性和防篡改 很多数据在传输中都进行了加密 加密可分为三大类 对称加密 非对称加密 摘要算法 二 对称加密 采用单钥密码系统的加密方法 同一个密钥可以同时作用信息的加密和解密 该方法称为
  • C++中使用tuple

    本文讨论的是在C 11标准下使用tuple 而不是python语言 说到tuple 肯定会第一时间想到python语言 但tuple也不仅仅只在python中有 在C C 等语言中都有这样的数据结构 在C 中的tuple和python语言中
  • 解决VS无法识别手动创建的app.manifest文件的问题

    解决VS无法识别手动创建的app manifest文件的问题 解决方案 删除手动添加的app manifest文件 修改项目属性使项目自动添加app manifest文件 操作流程 1 选择当前项目 单击鼠标右键 选择 属性 2 在 属性
  • 语言小型心形图案代码_C语言写一个小程序,胖胖的爱心桃

    学了这么久的C语言 你是不是有很多会写的小玩意了呢 比如说简单的五角星 三角形 等腰三角形 心形之类的 笔者今天发现了个以前写的一个很好玩的小程序分享给大家 画心的C语言 include
  • python 对二维列表的排序

    例如 这样的列表 对它进行排序 第一种 使用lambda对列表中的数据进行排序 如果不懂lambda的可以去百度哦 有很多详细内容 按数字排序 mylist 张三 0 3 李四 0 4 王五 0 8 谢大脚 0 9 谢广坤 0 1 myli
  • edp和edt哪个好_香水edp和edt的区别

    在香水瓶子上 通常会看到edp和edt的标志 它们的具体区别如下 1 含义不同 E D P是Eau de Parfum的缩写 意思是淡香精 而E D T是Eau de Toilette的缩写 意思是淡香水 2 香精浓度不同 E D P的纯香
  • 以图搜图算法java_龙猫数据爬图新姿势:以图搜图

    如果说购物网站近两年有什么新变化 除了商品类别增多以外 以图搜图功能绝对算很重要的一个 看到自己喜欢的东西根本不用问具体信息 随手一拍马上就能在购物网站找同款 识别率相当高 真是方便又快捷 今天我们就来介绍下 这么好用的生产力工具是如何 进
  • Hiredis_API说明

    转 https blog csdn net xumaojun article details 51597468 同步的API接口 redisContext redisConnect const char ip int port void r
  • Qt信号与槽的Connect详解

    QT通过connect关联信号和槽函数 一 槽函数的执行是同步还是异步 在同一个线程中 Qt信号槽的执行是同步的 当一个信号被发射时 槽函数会立即被调用 而不是被放入事件队列中 这是因为在同一个线程中 事件循环和槽函数都是在同一个线程中执行
  • MySQL——索引

    文章目录 1 简介 2 索引的分类 2 1 主键索引 PRIMARy KEY 2 2 唯一索引 UNIQUE KEY 2 3 常规索引 KEY INDEX 2 4 全文索引 FullText 3 测试索引 3 1 创建100万条数据 3 2
  • 2013年8月27日星期一(DEMO7-19窗口的裁剪等)

    OK 现在马不停蹄 结束这个第7章 拖延的时间真长 有6个月了 汗 这个是上次的应用 加上逻辑判断如何画点 并用GetWindowRect 是客户区 实际上这不对 应该是GetClientRect 果然不对 只能是说把图画上了 代码如下 D
  • egret 学习笔记

    1 egret 的res模块新版不在引擎中
  • C#系列-函数

    一 方法 using System using System Collections Generic using System Linq using System Text using System Threading Tasks name
  • go中的线程的实现模型-P G M的调度

    线程实现模型 go中线程的实现是依靠 P G M M machine的缩写 一个M代表一个内核线程 或称 工作线程 P processor的缩写 一个P代表执行一个Go代码片段所需要的资源 或称 上下文环境 G goroutine的缩写 一
  • 安卓开发百度地图鉴权错误

    报错信息 E baidumapsdk Authentication Error 鉴权错误信息 sha1 package 52 C3 39 A9 18 FC C5 0D 55 EB EC A1 D9 EF F0 D2 F9 7D 12 AA
  • JAVA中String的常用方法

    String类在所有项目开发里面一定会用到 因此String类提供了一系列的功能操作方法 字符和字符串 String类与字符之间的转换 方法名称 类型 描述 public String char value 构造 将字符数组转换为Strin
  • 再临SpringBoot——同步异步、阻塞非阻塞、NIO与Reactor模式

    文章目录 同步 异步 阻塞 非阻塞 Proactor 与 Reactor 模式 Reactor Proactor NIO 同步 异步 阻塞 非阻塞 在高性能的I O设计中 有两个比较著名的模式Reactor和Proactor模式 其中Rea
  • python中pydantic库

    文章目录 pydantic库详解 一 概述 1 简介 2 优势 3 环境配置 二 Model 1 模型属性 2 基本使用 3 数据导入 3 1 orm 3 2 pickle 3 3 json 4 数据导出 三 验证器 1 类内添加 2 重用