首页 > 其他分享 >【2.1】Pydantic使用方法

【2.1】Pydantic使用方法

时间:2023-10-01 15:49:40浏览次数:43  
标签:__ friends signup datetime time 2.1 方法 id Pydantic

【一】介绍

Data validation and settings management using python type annotations.
使用Python的类型注解来进行数据校验和settings管理

pydantic enforces type hints at runtime, and provides user friendly errors when data is invalid.
Pydantic可以在代码运行时提供类型提示,数据校验失败时提供友好的错误提示

Define how data should be in pure, canonical python; validate it with pydantic.
定义数据应该如何在纯规范的Python代码中保存,并用Pydantic验证它

【二】类模型定义及使用

【1】使用 pydantic 语法创建模型类

# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel
from datetime import datetime
from typing import List, Optional


# 【1】定义模型类
class User(BaseModel):
    # 定义模型类中的属性
    # 定义 ID 为 int 类型 , 没有指定 默认字段 则表示该字段为必填字段,初始化类时需要传入参数
    id: int  # 必填字段
    # 定义 name 为 str 类型并指定一个默认值
    name: str = 'dream'  # 选填字段
    # 定义 signup_time 为 datetime 类型 (需导入包 datetime) 并用 Optional 初始化
    signup_time: Optional[datetime] = None
    # 定义 friends 为 List 类型 并且规定元素类型为 int 同时指定一个默认空列表
    friends: List[int] = []  # 列表中的元素是int类型,或者可以直接转换成 int 类型
    '''
    注意字符串包裹的 int 类型 也可以 将 str 类型 强转成 int 类型
        比如 '1' ---> 1
    '''

【2】创建数据格式字典

# 【2】创建数据格式字典
external_data = {
    # id 自定义
    'id': "123",
    # 名称默认
    # signup_time 使用 自定义时间格式 --- 可以被识别的格式
    'signup_time': '2023-9-25 16:56:22',
    # friends 传入 int 类型  或者可以被 int 强转的 str 类型
    'friends': [1, 2, '3', '4']
}

【3】初始化模型类

# 【3】初始化模型类
user = User(**external_data)
print(f'当前对象 :>>> {user}')
print(f"当前对象属性 :>>>> {dir(user)}")

# 调用属性
print(user.id)
print(user.friends)
print(repr(user.signup_time))

# 输出对象数据为字典格式
print(user.dict())
当前对象 :>>> id=123 name='dream' signup_time=datetime.datetime(2023, 9, 25, 16, 56, 22) friends=[1, 2, 3, 4]

当前对象属性 :>>>> ['Config', '__abstractmethods__', '__annotations__', '__class__', '__config__', '__custom_root_type__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__fields__', '__fields_set__', '__format__', '__ge__', '__get_validators__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__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__', '__schema_cache__', '__setattr__', '__setstate__', '__signature__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__validators__', '__values__', '_abc_impl', '_calculate_keys', '_decompose_class', '_get_value', '_init_private_attributes', '_iter', 'construct', 'copy', 'dict', 'fields', 'friends', 'from_orm', 'id', 'json', 'name', 'parse_file', 'parse_obj', 'parse_raw', 'schema', 'schema_json', 'signup_time', 'to_string', 'update_forward_refs', 'validate']

123

[1, 2, 3, 4]

datetime.datetime(2023, 9, 25, 16, 56, 22)

{'id': 123, 'name': 'dream', 'signup_time': datetime.datetime(2023, 9, 25, 16, 56, 22), 'friends': [1, 2, 3, 4]}

【4】模型类初识化遇到的异常处理

  • 如果传入的类型与模型中的定义不符
# 【2】创建数据格式字典
external_data = {
    # id 自定义
    'id': "a123",
    # 名称默认
    # signup_time 使用 自定义时间格式 --- 可以被识别的格式
    'signup_time': '2023-9-25 16:56:22',
    # friends 传入 int 类型  或者可以被 int 强转的 str 类型
    'friends': [1, 2, '3', '4']
}

user = User(**external_data)
  • 报错如下
value is not a valid integer (type=type_error.integer)

【5】序列化异常信息

  • 捕获到异常并序列化异常格式化输出
# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel, ValidationError
from datetime import datetime
from typing import List, Optional


# 【1】定义模型类
class User(BaseModel):
    # 定义模型类中的属性
    # 定义 ID 为 int 类型 , 没有指定 默认字段 则表示该字段为必填字段,初始化类时需要传入参数
    id: int  # 必填字段
    # 定义 name 为 str 类型并指定一个默认值
    name: str = 'dream'  # 选填字段
    # 定义 signup_time 为 datetime 类型 (需导入包 datetime) 并用 Optional 初始化
    signup_time: Optional[datetime] = None
    # 定义 friends 为 List 类型 并且规定元素类型为 int 同时指定一个默认空列表
    friends: List[int] = []  # 列表中的元素是int类型,或者可以直接转换成 int 类型
    '''
    注意字符串包裹的 int 类型 也可以 将 str 类型 强转成 int 类型
        比如 '1' ---> 1
    '''
    
# 捕获到 格式 的异常并序列化输出
try:
    User(id=1, signup_time=datetime.today(), friends=['1', 2, 'not number'])
except ValidationError as e:
    print(f'捕获到异常 :>>>> {e.json()}')
捕获到异常 :>>>> [
  {
    "loc": [
      "friends",
      2
    ],
    "msg": "value is not a valid integer",
    "type": "type_error.integer"
  }
]

【6】模型类的方法介绍

# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel, ValidationError
from datetime import datetime
from typing import List, Optional


# 【1】定义模型类
class User(BaseModel):
    # 定义模型类中的属性
    # 定义 ID 为 int 类型 , 没有指定 默认字段 则表示该字段为必填字段,初始化类时需要传入参数
    id: int  # 必填字段
    # 定义 name 为 str 类型并指定一个默认值
    name: str = 'dream'  # 选填字段
    # 定义 signup_time 为 datetime 类型 (需导入包 datetime) 并用 Optional 初始化
    signup_time: Optional[datetime] = None
    # 定义 friends 为 List 类型 并且规定元素类型为 int 同时指定一个默认空列表
    friends: List[int] = []  # 列表中的元素是int类型,或者可以直接转换成 int 类型
    '''
    注意字符串包裹的 int 类型 也可以 将 str 类型 强转成 int 类型
        比如 '1' ---> 1
    '''


# 【2】创建数据格式字典
external_data = {
    # id 自定义
    'id': "123",
    # 名称默认
    # signup_time 使用 自定义时间格式 --- 可以被识别的格式
    'signup_time': '2023-9-25 16:56:22',
    # friends 传入 int 类型  或者可以被 int 强转的 str 类型
    'friends': [1, 2, '3', '4']
}

# 【3】初始化模型类
user = User(**external_data)


print("\033[31m3. --- 模型类的的属性和方法 ---\033[0m")
  • 字典序列化
# 字典序列化
print(user.dict())
{'id': 123, 'name': 'dream', 'signup_time': datetime.datetime(2023, 9, 25, 16, 56, 22), 'friends': [1, 2, 3, 4]}
  • json序列化
# json序列化
print(user.json())
{"id": 123, "name": "dream", "signup_time": "2023-09-25T16:56:22", "friends": [1, 2, 3, 4]}
  • copy数据 (注意这里的 copy 是浅拷贝)
# copy数据 (注意这里的 copy 是浅拷贝)
print(user.copy())
id=123 name='dream' signup_time=datetime.datetime(2023, 9, 25, 16, 56, 22) friends=[1, 2, 3, 4]
  • 使用解包的方式解析数据
# 使用解包的方式解析数据 (使用 类去解析数据生成对象)
print(User.parse_obj(obj=external_data))
id=123 name='dream' signup_time=datetime.datetime(2023, 9, 25, 16, 56, 22) friends=[1, 2, 3, 4]
  • 解析原生的字符串数据
# 解析原生的数据 (使用 类去解析数据生成对象)
print(User.parse_raw('{"id": "123", "signup_ts": "2020-12-22 12:22", "friends": [1, 2, "3"]}'))
id=123 name='dream' signup_time=None friends=[1, 2, 3]
  • 解析文件中的数据
# 准备数据方式一:新建pydantic_data.json
# 写入如下数据
{"id": "123", "signup_ts": "2020-12-22 12:22", "friends": [1, 2, "3"]}

# 准备数据方式二:使用pathliub模块
from pathlib import Path

path = Path('pydantic_data.json')
path.write_text('{"id": "123", "signup_ts": "2020-12-22 12:22", "friends": [1, 2, "3"]}')
# 解析文件中的数据
print(User.parse_file('pydantic_data.json'))
id=123 name='dream' signup_time=None friends=[1, 2, 3]
  • 得到对象更多的信息
# 得到的对象包含更多的信息
print(user.schema())
print(user.schema_json())
{'title': 'User', 'type': 'object', 'properties': {'id': {'title': 'Id', 'type': 'integer'}, 'name': {'title': 'Name', 'default': 'dream', 'type': 'string'}, 'signup_time': {'title': 'Signup Time', 'type': 'string', 'format': 'date-time'}, 'friends': {'title': 'Friends', 'default': [], 'type': 'array', 'items': {'type': 'integer'}}}, 'required': ['id']}

{"title": "User", "type": "object", "properties": {"id": {"title": "Id", "type": "integer"}, "name": {"title": "Name", "default": "dream", "type": "string"}, "signup_time": {"title": "Signup Time", "type": "string", "format": "date-time"}, "friends": {"title": "Friends", "default": [], "type": "array", "items": {"type": "integer"}}}, "required": ["id"]}
  • 不检验数据直接创建模型类
# 不检验数据直接创建模型类,不建议在construct方法中传入未经验证的数据
# id是字符串 是错误的
user_data = {"id": "error", "signup_ts": "2020-12-22 12 22", "friends": [1, 2, 3]}
print(User.construct(**user_data))
name='dream' signup_time=None friends=[1, 2, 3] id='error' signup_ts='2020-12-22 12 22'
  • 查看当前模型类中的所有的字段
# 查看当前模型类中的所有的字段
# 定义模型类的时候,所有字段都注明类型,字段顺序就不会乱
print(User.__fields__.keys())
name='dream' signup_time=None friends=[1, 2, 3] id='error' signup_ts='2020-12-22 12 22'
dict_keys(['id', 'name', 'signup_time', 'friends'])

【三】递归模型

  • 在一个类模型中调用另一个类模型

【1】创建模型类

# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel, ValidationError
from datetime import datetime, time
from typing import List, Optional

# 定义一个 叫声类
class Sound(BaseModel):
    sound: str

# 定义一个 狗 类
class Dog(BaseModel):
    birthday: time
    weight: float = Optional[None]
    # 不同的狗有不同的叫声。递归模型(Recursive Models)就是指一个嵌套一个
    # 狗的叫声有很多种,并且这些叫声都是 Sound 类型的
    sound: List[Sound]

【2】创建数据格式

dog_data = {
    'birthday': date.today(),
    'weight': 6.66,
    'sound': [{"sound": "wang wang ~"}, {"sound": "ying ying ~"}],
}

【3】初始化对象

dog = Dog(**dog_data)
print(dog.dict())
{'birthday': datetime.date(2023, 9, 28), 'sound': [{'sound': 'wang wang ~'}, {'sound': 'ying ying ~'}]}

【四】ORM类型

  • ORM模型:从类实例创建符合ORM对象的模型

【1】创建模型表

# 导入 pydantic 中的 BaseModel 模型类
from pydantic import BaseModel, constr
from typing import List

# 导入字段
from sqlalchemy import Column, String, Integer
# 导入元组类
from sqlalchemy.dialects.postgresql import ARRAY
# 声明
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


# 【1】创建表
class CompanyOrm(Base):
    # 表名
    __tablename__ = 'companies'
    # 创建 字段 ID 为 Integer 类型且为主键,不能为空
    id = Column(Integer, primary_key=True, nullable=False)
    # 创建 字段 public_key 为 String 类型 ,且指明长度 为 20 , index 建立索引,nullable 不能为空,unique 唯一
    public_key = Column(String(20), index=True, nullable=False, unique=True)
    # 创建 字段 name 为 String 类型,指明长度 63 ,unique 唯一
    name = Column(String(63), unique=True)
    # 创建字段 domains 为 ARRAY (元组) 类型,且元组中的元素类型为 String 类型 ,指明长度 为 255
    domains = Column(ARRAY(String(255)))

【2】定义 ORM 模型表

# 【2】创建表 --- 定义一个表与上面的字段类型一样
class CompanyModel(BaseModel):
    id: int
    # constr 限制字符串
    public_key: constr(max_length=20)
    name = constr(max_length=63)
    domains: List[constr(max_length=255)]

    # 定义配置
    class Config:
        orm_mode = True

【3】创建数据字典

# 【3】创建数据字典
orm_data = {
    "id": "123",
    "public_key": "strawberry",
    "name": "Dream",
    "domains": ['example.com', 'dream.com'],
}

【4】实例化表模型对象

# 【4】实例化的到 表模型 对象
co_orm = CompanyOrm(**orm_data)

【5】实例化得到 ORM 对象

# 【5】实例化得到 ORM 对象
# ORM模型:从类实例创建符合ORM对象的模型
# co_orm 是 类的实例 使用 CompanyModel.from_orm 去校验他的数据类型
# pydantic 定义的模型类的规范
orm_obj = CompanyModel.from_orm(co_orm)
print(orm_obj)
id=123 public_key='strawberry' domains=['example.com', 'dream.com']

【6】补充

  • 提醒:选择你安装的 pydantic 版本的官方文档查看,新的版本对相关的类型进行了更新

【补充】Pydantic 插件

  • 在 Pycharm 的 插件商店中
    • 也有 Pydantic 插件,可以选择性安装

image-20230928170712308

标签:__,friends,signup,datetime,time,2.1,方法,id,Pydantic
From: https://www.cnblogs.com/dream-ze/p/17738901.html

相关文章

  • 【2.0】Starlette,Pydantic 与 FastAPI 框架是什么关系?
    【一】介绍Starlette是个什么项目;IDE开发时Python3.5+版本的"typehints"的好处:简短、直观和标准的Python类型声明;介绍Pydantic包,FastAPI项目的开发为什么要使用Pydantic【二】Starlette【1】介绍Starlette是一种轻量级的ASGI框架/工具包,是构建高性能......
  • 我ios重启方法
    1、先按下「音量+」键,再快速松开; 2、再按下「音量-」键,快速松开; 3、最后长按机身右侧的「电源键」不放,直到出现苹果Logo界面到黑屏,则说明强制关机成功,这时就可以松开电源按键了。......
  • 利用PHP的数组splice方法进行高效数据删除和插入
    PHP数组是一个非常强大的数据结构,它可以存储多个值,并按照需要对这些值进行添加、删除或修改。在PHP中,我们可以使用splice方法对数组进行删除和插入操作,以实现高效的数据操作。本文将介绍如何使用数组splice方法进行数据删除和插入,并给出示例代码。一、使用splice方法进行数据删除......
  • 利用PHP的数组splice方法进行高效数据删除和插入
    PHP数组是一个非常强大的数据结构,它可以存储多个值,并按照需要对这些值进行添加、删除或修改。在PHP中,我们可以使用splice方法对数组进行删除和插入操作,以实现高效的数据操作。本文将介绍如何使用数组splice方法进行数据删除和插入,并给出示例代码。一、使用splice方法进行数据删除数......
  • Llama2-Chinese项目:2.1-Atom-7B预训练
    虽然Llama2的预训练数据相对于第一代LLaMA扩大了一倍,但是中文预训练数据的比例依然非常少,仅占0.13%,这也导致了原始Llama2的中文能力较弱。为了能够提升模型的中文能力,可以采用微调和预训练两种路径,其中:微调需要的算力资源少,能够快速实现一个中文Llama的雏形。但缺点也显而易见,只......
  • GO语言实战之接口实现与方法集
    写在前面嗯,学习GO,所以有了这篇文章博文内容为《GO语言实战》读书笔记之一主要涉及知识接口是什么方法集(值接收和指针接收)多态傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比......
  • java 实现模板方法模式
    模板方法模式(TemplateMethodPattern)是一种行为型设计模式,它定义了一个算法的骨架,将具体的步骤延迟到子类中实现。模板方法模式使得子类可以重新定义算法的某些步骤,而不改变算法的结构。以下是一个简单的Java示例,演示如何实现模板方法模式:首先,定义一个抽象类Game,它包含一个模板方......
  • Java Arrays.fill() 方法详解
    在Java编程中,数组是一个非常常见的数据结构,而Java提供了许多有用的数组操作方法来简化开发过程。其中之一是Arrays.fill()方法,它允许我们填充一个数组的所有元素,将它们设置为指定的值。在本篇文章中,我们将深入探讨Arrays.fill()方法的用法、参数和示例,以帮助您更好地理解和使用它。......
  • VScode中下载了插件但是无法找到SSH Target连接服务器的解决方法(CANNOT find SSH Targ
    VSCode版本vscodeversion:(version1.82)已下载扩展installedextensions:Remote-SSHv0.106.4Remote-SSH:EditingConfigurationFilesv0.86.0RemoteDevelopmentv0.24.0WSLv0.81.3几天前我从pycharm转战vscode,在连接服务器时遇到了一些问题。根据一些较为古早的......
  • 如何搭建团队知识库?试试新的工具和方法吧!
    知识本身没有价值,只有被利用的知识才能发挥作用。我们经常见到有许多“宏伟”的团队知识库,但是从来没有人去用……搭建团队知识库没有人用的团队知识库存在的问题是“我们知道所有问题的答案,就是不知道问题是什么”。如何建立团队知识库与具体的业务的关联、打破知识业务“两张皮......