今天的主题是使用 Python 类型提示进行数据验证和设置管理。我们将使用一个名为的 Python 包pydantic,它在运行时强制执行类型提示。它提供了对用户友好的错误,允许你捕获任何无效数据。根据官方文档,Pydantic 是
“……主要是一个解析库,而不是验证库。验证是达到目的的一种手段:建立一个符合所提供的类型和约束的模型。
换句话说,pydantic 保证输出模型的类型和约束,而不是输入数据。”
基本安装
打开终端并运行以下命令进行安装pydantic
pip install pydantic
升级现有包
如果你已经有一个现有的软件包并想升级它,请运行以下命令:
pip install -U pydantic
可选依赖项
pydantic根据你的需要附带以下可选依赖项:
- email-validator— 支持电子邮件验证。
- typing-extensions— 支持使用LiteralPython 3.8 之前的版本。
- python-dotenv— 支持dotenv带有设置的文件。
你可以手动安装它们:
# install email-validator
pip install email-validator
# install typing-extensions
pip install typing_extensions
# install python-dotenv
pip install python-dotenv
或连同pydantic如下:
# install email-validator
pip install pydantic[email]
# install typing-extensions
pip install pydantic[typing_extensions]
# install python-dotenv
pip install pydantic[dotenv]
# install all dependencies
pip install pydantic[email,typing_extensions,dotenv]
怎么使用Pydantic
在本节中,我们将探索怎么使用pydantic.
在中定义一个对象pydantic就像创建一个继承自BaseModel. 当你从类创建新对象时,pydantic保证生成的模型实例的字段将符合模型上定义的字段类型。
- 导入Pydanic
在 Python 文件的顶部添加以下导入声明。
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel
用户类
声明一个继承BaseModel如下的新类:
class User(BaseModel):
id: int
username : str
password : str
confirm_password : str
alias = 'anonymous'
timestamp: Optional[datetime] = None
friends: List[int] = []
pydantic使用内置的类型提示语法来确定每个变量的数据类型。让我们一一探究幕后发生的事情。
- id表示一个整型变量代表一个 ID。由于未提供默认值,因此该字段是必需的,并且必须在创建对象时指定。如果可能,字符串、字节或浮点数将被强制转换为整数;否则,将引发异常。
- username 表示字符串变量表示用户名并且是必需的。
- password表示字符串变量表示密码并且是必需的。
- confirm_password表示字符串变量表示确认密码并且是必需的。稍后将用于数据验证。
- alias 表示字符串变量表示别名。它不是必需的,如果在对象创建期间未提供,将设置为匿名。
- timestamp表示日期/时间字段,不是必需的。默认为无。pydantic 将处理 unix 时间戳 int 或表示日期/时间的字符串。
- friends— 整数输入列表。
对象实例化
从User类中实例化一个新对象。
data = {'id': '1234', 'username': 'Jack', 'password': 'Password123', 'confirm_password': 'Password123', 'timestamp': '2020-08-03 10:30', 'friends': [1, '2', b'3']}
user = User(**data)
user打印出变量时,你应该得到以下输出。你会注意到它id已自动转换为整数,即使输入是字符串也是如此。同样,字节会自动转换为整数,如friends字段所示。
id=1234 username='Jack' password='Password123' confirm_password='Password123' timestamp=datetime.datetime(2020, 8, 3, 10, 30)
friends=[1, 2, 3] alias='anonymous'
BaseModel下的方法和属性
继承 的类BaseModel将具有以下方法和属性:
- dict()— 返回模型字段和值的字典
- json()— 返回一个 JSON 字符串表示字典
- copy()— 返回模型的深层副本
- parse_obj()— 如果对象不是字典,则用于将任何对象加载到模型中并进行错误处理的实用程序
- parse_raw()— 用于加载多种格式字符串的实用程序
- parse_field()— 类似于parse_raw()但适用于文件
- from_orm() — 将数据从任意类加载到模型中
- schema() — 返回将模型表示为 JSON 模式的字典
- schema_json()— 返回 JSON 字符串表示形式schema()
- construct()— 一种无需运行验证即可创建模型的类方法
- __fields_set__— 初始化模型实例时设置的字段名称集
- __fields__— 模型字段的字典
- __config__ — 模型的配置类
让我们将 for 的输入更改为id字符串,如下所示:
data = {'id': 'a random string', 'username':
'Jack', 'password': 'Password123',
'confirm_password': 'Password123', 'timestamp': '2020-08-03 10:30', 'friends': [1, '2', b'3']}
user = User(**data)
运行代码时应该会出现以下错误。
value is not a valid integer (type=type_error.integer)
验证错误
为了更好地了解错误的详细信息,强烈建议将其包装在 try-catch 块中,如下所示:
from pydantic import BaseModel, ValidationError
# ... codes for User class
data = {'id': 'a random string', 'username': 'wai foong', 'password': 'Password123', 'confirm_password': 'Password123', 'timestamp': '2020-08-03 10:30', 'friends': [1, '2', b'3']}
try:
user = User(**data)
except ValidationError as e:
print(e.json())
它将打印出以下 JSON,这表明输入的id不是有效整数。
[
{
"loc": [
"id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
字段类型
pydantic为 Python 标准库中的大多数常见类型提供支持。完整名单如下:
- bool
- int
- float
- str
- bytes
- list
- tuple
- dict
- set
- frozenset
- datetime.date
- datetime.time
- datetime.datetime
- datetime.timedelta
- typing.Any
- typing.TypeVar
- typing.Union
- typing.Optional
- typing.List
- typing.Tuple
- typing.Dict
- typing.Set
- typing.FrozenSet
- typing.Sequence
- typing.Iterable
- typing.Type
- typing.Callable
- typing.Pattern
- ipaddress.IPv4Address
- ipaddress.IPv4Interface
- ipaddress.IPv4Network
- ipaddress.IPv6Address
- ipaddress.IPv6Interface
- ipaddress.IPv6Network
- enum.Enum
- enum.IntEnum
- decimal.Decimal
- pathlib.Path
- uuid.UUID
- ByteSize
约束类型
你可以通过Constrained Types. 让我们看看下面的例子:
from pydantic import (
BaseModel,
NegativeInt,
PositiveInt,
conint,
conlist,
constr
)
class Model(BaseModel):
# minimum length of 2 and maximum length of 10
short_str: constr(min_length=2, max_length=10)
# regex
regex_str: constr(regex=r'^apple (pie|tart|sandwich)$')
# remove whitespace from string
strip_str: constr(strip_whitespace=True)
# value must be greater than 1000 and less than 1024
big_int: conint(gt=1000, lt=1024)
# value is multiple of 5
mod_int: conint(multiple_of=5)
# must be a positive integer
pos_int: PositiveInt
# must be a negative integer
neg_int: NegativeInt
# list of integers that contains 1 to 4 items
严格类型
如果你正在寻找当且仅当验证值属于相应类型或该类型的子类型时通过验证的严格限制,你可以使用以下严格类型:
- 严格的字符串
- 严格整数
- 严格浮动
- 严格布尔
以下示例说明了StrictBool在继承类中强制执行的正确方法。
from pydantic import BaseModel, StrictBool,
class StrictBoolModel(BaseModel):
strict_bool: StrictBool
该字符串‘False’将引发 ValidationError 因为它只接受TrueorFalse作为输入。
验证器
validator此外,你可以使用继承类中的装饰器创建自己的自定义验证器。让我们看一下下面的示例,它确定是否id是四位数字以及是否confirm_password与该password字段匹配。
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel, ValidationError, validator
class User(BaseModel):
id: int
username : str
password : str
confirm_password : str
alias = 'anonymous'
timestamp: Optional[datetime] = None
friends: List[int] = []
@validator('id')
def id_must_be_4_digits(cls, v):
if len(str(v)) != 4:
raise ValueError('must be 4 digits')
return v
@validator('confirm_password')
def passwords_match(cls, v, values, **kwargs):
if 'password' in values and v != values['password']:
raise ValueError('passwords do not match')
return v
结论
我们从 Pydantic 的详细解释开始,它有助于解析和验证数据。还包括根据我们的用例支持三个额外的依赖项。
完成安装后,我们深入探索了软件包提供的基本功能。基本构建块是创建一个继承自的新类BaseModel。
我们了解到,Pydantic 提供了对 Python 标准库下大部分常见数据类型的支持。我们测试了Constrained Types和Strict Types有助于执行我们自己的自定义限制。
最后,你尝试使用validator装饰器只允许输入四位数字id,并且confirm_password必须与password字段匹配。