python库pydantic的简易入门教程

目录
  • 一、简介
  • 二、安装
  • 三、常见模型
    • 1、BaseModel 基本模型
    • 2、递归模型
    • 3、GenericModel 通用模型(泛型):
  • 四、常用类型
  • 五、验证器
  • 六、配置
  • 七、与 mypy 一起使用
  • 总结

一、简介

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)
    """
    2 validation errors for Response[int]
    data
      value is not a valid integer (type=type_error.integer)
    error
      must provide data or error (type=value_error)
    """

4、create_model 动态模型

在某些情况下,直到运行时才知道模型的结构。为此 pydantic 提供了create_model允许动态创建模型的方法。

from pydantic import BaseModel, create_model
DynamicFoobarModel = create_model('DynamicFoobarModel', foo=(str, ...), bar=123)

四、常用类型

  • None,type(None)或Literal[None]只允许None值
  • bool 布尔类型
  • int 整数类型
  • float 浮点数类型
  • str 字符串类型
  • bytes 字节类型
  • list 允许list,tuple,set,frozenset,deque, 或生成器并转换为列表
  • tuple 允许list,tuple,set,frozenset,deque, 或生成器并转换为元组
  • dict 字典类型
  • set 允许list,tuple,set,frozenset,deque, 或生成器和转换为集合;
  • frozenset 允许list,tuple,set,frozenset,deque, 或生成器和强制转换为冻结集
  • deque 允许list,tuple,set,frozenset,deque, 或生成器和强制转换为双端队列
  • datetime 的date,datetime,time,timedelta 等日期类型
  • typing 中的 Deque, Dict, FrozenSet, List, Optional, Sequence, Set, Tuple, Union,Callable,Pattern等类型
  • FilePath,文件路径
  • DirectoryPath 目录路径
  • EmailStr 电子邮件地址
  • NameEmail 有效的电子邮件地址或格式
  • PyObject 需要一个字符串并加载可在该虚线路径中导入的 python 对象;
  • Color 颜色类型
  • AnyUrl 任意网址
  • SecretStr、SecretBytes 敏感信息,将被格式化为'**********'或''
  • Json 类型
  • PaymentCardNumber 支付卡类型
  • 约束类型,可以使用con*类型函数限制许多常见类型的值
    • conlist
  • item_type: Type[T]: 列表项的类型
  • min_items: int = None: 列表中的最小项目数
  • max_items: int = None: 列表中的最大项目数
  • conset
  • item_type: Type[T]: 设置项目的类型
  • min_items: int = None: 集合中的最小项目数
  • max_items: int = None: 集合中的最大项目数
  • conint
  • strict: bool = False: 控制类型强制
  • gt: int = None: 强制整数大于设定值
  • ge: int = None: 强制整数大于或等于设定值
  • lt: int = None: 强制整数小于设定值
  • le: int = None: 强制整数小于或等于设定值
  • multiple_of: int = None: 强制整数为设定值的倍数
  • confloat
  • strict: bool = False: 控制类型强制
  • gt: float = None: 强制浮点数大于设定值
  • ge: float = None: 强制 float 大于或等于设定值
  • lt: float = None: 强制浮点数小于设定值
  • le: float = None: 强制 float 小于或等于设定值
  • multiple_of: float = None: 强制 float 为设定值的倍数
  • condecimal
  • gt: Decimal = None: 强制十进制大于设定值
  • ge: Decimal = None: 强制十进制大于或等于设定值
  • lt: Decimal = None: 强制十进制小于设定值
  • le: Decimal = None: 强制十进制小于或等于设定值
  • max_digits: int = None: 小数点内的最大位数。它不包括小数点前的零或尾随的十进制零
  • decimal_places: int = None: 允许的最大小数位数。它不包括尾随十进制零
  • multiple_of: Decimal = None: 强制十进制为设定值的倍数
  • constr
  • strip_whitespace: bool = False: 删除前尾空格
  • to_lower: bool = False: 将所有字符转为小写
  • strict: bool = False: 控制类型强制
  • min_length: int = None: 字符串的最小长度
  • max_length: int = None: 字符串的最大长度
  • curtail_length: int = None: 当字符串长度超过设定值时,将字符串长度缩小到设定值
  • regex: str = None: 正则表达式来验证字符串
  • conbytes
  • strip_whitespace: bool = False: 删除前尾空格
  • to_lower: bool = False: 将所有字符转为小写
  • min_length: int = None: 字节串的最小长度
  • max_length: int = None: 字节串的最大长度
  • 严格类型,您可以使用StrictStr,StrictBytes,StrictInt,StrictFloat,和StrictBool类型,以防止强制兼容类型

五、验证器

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

关于验证器的一些注意事项:

  • 验证器是“类方法”,因此它们接收的第一个参数值是UserModel类,而不是UserModel
  • 第二个参数始终是要验证的字段值,可以随意命名
  • 单个验证器可以通过传递多个字段名称来应用于多个字段,也可以通过传递特殊值在所有字段上调用单个验证器'*'
  • 关键字参数pre将导致在其他验证之前调用验证器
  • 通过each_item=True将导致验证器被施加到单独的值(例如List,Dict,Set等),而不是整个对象
from typing import List
from pydantic import BaseModel, ValidationError, validator

class ParentModel(BaseModel):
    names: List[str]

class ChildModel(ParentModel):
    @validator('names', each_item=True)
    def check_names_not_empty(cls, v):
        assert v != '', 'Empty strings are not allowed.'
        return v

# This will NOT raise a ValidationError because the validator was not called
try:
    child = ChildModel(names=['Alice', 'Bob', 'Eve', ''])
except ValidationError as e:
    print(e)
else:
    print('No ValidationError caught.')
    #> No ValidationError caught.

class ChildModel2(ParentModel):
    @validator('names')
    def check_names_not_empty(cls, v):
        for name in v:
            assert name != '', 'Empty strings are not allowed.'
        return v

try:
    child = ChildModel2(names=['Alice', 'Bob', 'Eve', ''])
except ValidationError as e:
    print(e)
    """
    1 validation error for ChildModel2
    names
      Empty strings are not allowed. (type=assertion_error)
    """
  • 关键字参数 always 将导致始终验证,出于性能原因,默认情况下,当未提供值时,不会为字段调用验证器。然而,在某些情况下,始终调用验证器可能很有用或需要,例如设置动态默认值。
  • allow_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)

六、配置

如果您创建一个继承自BaseSettings的模型,模型初始化程序将尝试通过从环境中读取,来确定未作为关键字参数传递的任何字段的值。(如果未设置匹配的环境变量,则仍将使用默认值。)

这使得很容易:

  • 创建明确定义、类型提示的应用程序配置类
  • 自动从环境变量中读取对配置的修改
  • 在需要的地方手动覆盖初始化程序中的特定设置(例如在单元测试中)
from typing import Set

from pydantic import (
    BaseModel,
    BaseSettings,
    PyObject,
    RedisDsn,
    PostgresDsn,
    Field,
)

class SubModel(BaseModel):
    foo = 'bar'
    apple = 1

class Settings(BaseSettings):
    auth_key: str
    api_key: str = Field(..., env='my_api_key')

    redis_dsn: RedisDsn = 'redis://user:pass@localhost:6379/1'
    pg_dsn: PostgresDsn = 'postgres://user:pass@localhost:5432/foobar'

    special_function: PyObject = 'math.cos'

    # to override domains:
    # export my_prefix_domains='["foo.com", "bar.com"]'
    domains: Set[str] = set()

    # to override more_settings:
    # export my_prefix_more_settings='{"foo": "x", "apple": 1}'
    more_settings: SubModel = SubModel()

    class Config:
        env_prefix = 'my_prefix_'  # defaults to no prefix, i.e. ""
        fields = {
            'auth_key': {
                'env': 'my_auth_key',
            },
            'redis_dsn': {
                'env': ['service_redis_dsn', 'redis_url']
            }
        }

print(Settings().dict())
"""
{
    'auth_key': 'xxx',
    'api_key': 'xxx',
    'redis_dsn': RedisDsn('redis://user:pass@localhost:6379/1',
scheme='redis', user='user', password='pass', host='localhost',
host_type='int_domain', port='6379', path='/1'),
    'pg_dsn': PostgresDsn('postgres://user:pass@localhost:5432/foobar',
scheme='postgres', user='user', password='pass', host='localhost',
host_type='int_domain', port='5432', path='/foobar'),
    'special_function': <built-in function cos>,
    'domains': set(),
    'more_settings': {'foo': 'bar', 'apple': 1},
}
"""

支持 Dotenv 文件设置变量,pydantic 有两种方式加载它:

class Settings(BaseSettings):
    ...

    class Config:
        env_file = '.env'
        env_file_encoding = 'utf-8'

或者

settings=Settings(_env_file='prod.env',_env_file_encoding='utf-8')

即使使用 dotenv 文件,pydantic 仍会读取环境变量,环境变量将始终优先于从 dotenv 文件加载的值。

pydantic 支持设置敏感信息文件,同样有2种方式加载:

class Settings(BaseSettings):
    ...
    database_password: str
    class Config:
        secrets_dir = '/var/run'

或者:

settings = Settings(_secrets_dir='/var/run')

即使使用 secrets 目录,pydantic仍会从 dotenv 文件或环境中读取环境变量,dotenv 文件和环境变量将始终优先于从 secrets 目录加载的值。

七、与 mypy 一起使用

Pydantic 附带了一个 mypy 插件,向 mypy 添加了许多重要的特定于 pydantic 的功能,以提高其对代码进行类型检查的能力。

例如以下脚本:

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

class Model(BaseModel):
    age: int
    first_name = 'John'
    last_name: NoneStr = None
    signup_ts: Optional[datetime] = None
    list_of_ints: List[int]

m = Model(age=42, list_of_ints=[1, '2', b'3'])
print(m.middle_name)  # not a model field!
Model()  # will raise a validation error for age and list_of_ints

在没有任何特殊配置的情况下,mypy 会捕获其中一个错误:

13: error: "Model" has no attribute "middle_name"

启用插件后,它会同时捕获:

13: error: "Model" has no attribute "middle_name"
16: error: Missing named argument "age" for "Model"
16: error: Missing named argument "list_of_ints" for "Model"

要启用该插件,只需添加pydantic.mypy到mypy 配置文件中的插件列表:

[mypy]
plugins = pydantic.mypy

要更改插件设置的值,请​​在 mypy 配置文件中创建一个名为 的部分[pydantic-mypy],并为要覆盖的设置添加键值对:

[mypy]
plugins = pydantic.mypy

follow_imports = silent
warn_redundant_casts = True
warn_unused_ignores = True
disallow_any_generics = True
check_untyped_defs = True
no_implicit_reexport = True

# for strict mypy: (this is the tricky one :-))
disallow_untyped_defs = True

[pydantic-mypy]
init_forbid_extra = True
init_typed = True
warn_required_dynamic_aliases = True
warn_untyped_fields = True

总结

到此这篇关于python库pydantic简易入门的文章就介绍到这了,更多相关python库pydantic教程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python编程pydantic触发及访问错误处理

    目录 常见触发错误的情况 错误的触发 注意 访问错误的方式 简单栗子 复杂栗子 自定义错误 自定义错误模板类 PydanticValueError 常见触发错误的情况 如果传入的字段多了会自动过滤 如果传入的少了会报错,必填字段 如果传入的字段名称对不上也会报错 如果传入的类型不对会自动转换 如果不能转换则会报错 错误的触发 pydantic 会在它正在验证的数据中发现错误时引发 ValidationError 注意 验证代码不应该抛出 ValidationError 本身 而是应该抛出 Val

  • python库pydantic的简易入门教程

    目录 一.简介 二.安装 三.常见模型 1.BaseModel 基本模型 2.递归模型 3.GenericModel 通用模型(泛型): 四.常用类型 五.验证器 六.配置 七.与 mypy 一起使用 总结 一.简介 pydantic 库是 python 中用于数据接口定义检查与设置管理的库. pydantic 在运行时强制执行类型提示,并在数据无效时提供友好的错误. 它具有如下优点: 与 IDE/linter 完美搭配,不需要学习新的模式,只是使用类型注解定义类的实例 多用途,BaseSett

  • python第三方库visdom的使用入门教程

    概述 Visdom:一个灵活的可视化工具,可用来对于 实时,富数据的 创建,组织和共享.支持Torch和Numpy还有pytorch. visdom 可以实现远程数据的可视化,对科学实验有很大帮助.我们可以远程的发送图片和数据,并进行在ui界面显示出来,检查实验结果,或者debug. 要用这个先要安装,对于python模块而言,安装都是蛮简单的: pip install visdom 安装完每次要用直接输入代码打开: python -m visdom.server 然后根据提示在浏览器中输入相应

  • Python pyecharts模块安装与入门教程

    目录 pyecharts产生背景 一.pyecharts模块安装 二.pyecharts入门 1.基础折线图 2.pyecharts配置选项 pyecharts产生背景 Echarts是由百度开源的数据可视化,凭借良好的交互性和精巧的图表设计,得到众多开发者的认可,而python很适合用于数据处理,数据分析遇到数据可视化时pyecharts就产生了. 官网链接:https://pyecharts.org/#/ 画廊pyecharts-gallery pyecharts支持的图表众多,官方提供了画

  • Python中Scrapy框架的入门教程分享

    目录 前言 安装Scrapy 创建一个Scrapy项目 创建一个爬虫 运行爬虫 结论 前言 Scrapy是一个基于Python的Web爬虫框架,可以快速方便地从互联网上获取数据并进行处理.它的设计思想是基于Twisted异步网络框架,可以同时处理多个请求,并且可以使用多种处理数据的方式,如提取数据.存储数据等. 本教程将介绍如何使用Scrapy框架来编写一个简单的爬虫,从而让您了解Scrapy框架的基本使用方法. 安装Scrapy 首先,您需要在您的计算机上安装Scrapy框架.您可以使用以下命

  • JS库之Three.js 简易入门教程(详解之一)

    开场白 webGL可以让我们在canvas上实现3D效果.而three.js是一款webGL框架,由于其易用性被广泛应用.如果你要学习webGL,抛弃那些复杂的原生接口从这款框架入手是一个不错的选择. 博主目前也在学习three.js,发现相关资料非常稀少,甚至官方的api文档也非常粗糙,很多效果需要自己慢慢敲代码摸索.所以我写这个教程的目的一是自己总结,二是与大家分享. 本篇是系列教程的第一篇:入门篇.在这篇文章中,我将以一个简单的demo为例,阐述three.js的基本配置方法.学完这篇文章

  • Python 音视频剪辑快速入门教程

    目录 一.引言 二.Moviepy 简介 三.Moviepy 安装 四.音视频的加载和保存 五.音视频数据的访问 六.音视频变换 1.Clip 的 fl 方法 2.Clip 的 fl_time 方法 3.剪辑颜色变换 4.剪辑大小变换 5.剪辑内容变换 七.剪辑合成 1.概述 2.将多个剪辑拼接 3.多个剪辑同屏播放 4.将一系列图像构造成视频 5.其他几种生成视频方法简介 八.小结 一.引言 在这个短视频和自媒体大行其道的年代,音视频剪辑成为了大佬们的必备工具,现在有很多音视频剪辑的软件,如剪

  • 全网最全python库selenium自动化使用详细教程

    一.安装selenium pip install Selenium 二.初始化浏览器 Chrome 是初始化谷歌浏览器 Firefox 是初始化火狐浏览器 Edge 是初始化IE浏览器 PhantomJS 是一个无界面浏览器. from selenium import webdriver driver = webdriver.Chrome() 三.设置浏览器大小 maximize_window 最大化窗口 set_window_size 自定义窗口大小 from selenium import

  • Python Matplotlib初阶使用入门教程

    目录 0. 前言 1. 创建Figure的两种基本方法 1.1 第1种方法 1.2 第2种方法 2. Figure的解剖图及各种基本概念 2.1 Figure 2.2 Axes 2.3 Axis 2.4 Artist 3. 绘图函数的输入 4. 面向对象接口与pyplot接口 5. 绘图复用实用函数例 0. 前言 本文介绍Python Matplotlib库的入门求生级使用方法. 为了方便以下举例说明,我们先导入需要的几个库.以下代码在Jupyter Notebook中运行. %matplotl

  • python实现的正则表达式功能入门教程【经典】

    本文讲述了python实现的正则表达式功能.分享给大家供大家参考,具体如下: 前文: 首先,什么叫正则表达式(Regular Expression)? 例如我们要判断字符串"adi_e32fv,Ls"里面是否含有子串"e32f",又例如我们在一个含百万个姓名的txt文件中找姓"王",名字以"五"结尾的名字,然后打印出来.结果为:"王五"."王小五"."王大五".&qu

  • Python面向对象思想与应用入门教程【类与对象】

    本文实例讲述了Python面向对象思想与应用.分享给大家供大家参考,具体如下: 面向对象思想 1.面向对象的设计思想 面向对象是基于万物皆对象这个哲学观点. 2.面向对象和面向过程的区别 面向过程 在生活中: 它是一种看待问题的思维方式,在思考问题的时候,着眼问题是怎样一步一步解决的,然后亲力亲为去解决问题[类似于公司里的执行者]. 在程序中: ​ 代码是从上而下顺序执行,各个模块之间的关系尽可能简单,在功能上相对独立,程序的流程在写程序的时候就已经决定. 面向对象 在生活中: 它是另一种看待问

随机推荐