Pydantic v2.9 现已发布!您现在可以通过 PyPI 或您喜欢的包管理器安装它。
pip install --upgrade pydantic
此版本包含 25 多位贡献者的工作成果!在这篇文章中,我们将介绍此版本的亮点。您可以在 GitHub 上查看完整的变更日志。
此版本包含重要的 性能改进、联合序列化改进 和一些 新功能。
新功能
complex
数字支持
我们已在 Pydantic 中添加了对标准库 complex
数字的支持。对于验证,我们支持 complex
实例和可以 解析 为 complex
数字的字符串。
from pydantic import TypeAdapter
ta = TypeAdapter(complex)
complex_number = ta.validate_python('1+2j')
assert complex_number == complex(1, 2)
assert ta.dump_json(complex_number) == b'"1+2j"'
显式 ZoneInfo
支持
Pydantic 现在显式支持 ZoneInfo
类型(在 Python v3.9+ 中)。以下是用新类型进行验证和序列化的示例。
from pydantic import TypeAdapter
from zoneinfo import ZoneInfo
ta = TypeAdapter(ZoneInfo)
tz = ta.validate_python('America/Los_Angeles')
assert tz == ZoneInfo('America/Los_Angeles')
assert ta.dump_json(tz) == b'"America/Los_Angeles"'
感谢 @Youssefares 的贡献!有关新实现的更多详细信息,请参阅 #9896。
val_json_bytes
设置
新的 val_json_bytes
设置允许用户指定在从 JSON 解码 bytes
数据时使用的编码。此设置与现有的 ser_json_bytes
结合使用,支持 bytes
数据的一致 JSON 往返操作。
例如
from pydantic import TypeAdapter, ConfigDict
ta = TypeAdapter(bytes, config=ConfigDict(ser_json_bytes='base64', val_json_bytes='base64'))
some_bytes = b'hello'
validated_bytes = ta.validate_python(some_bytes)
encoded_bytes = b'"aGVsbG8="'
assert ta.dump_json(validated_bytes) == encoded_bytes
# verifying round trip
# before we added support for val_json_bytes, the default encoding was 'utf-8' for validation, so this would fail
assert ta.validate_json(encoded_bytes) == validated_bytes
感谢 @josh-newman 的添加!您可以在 此处 查看完整的实现细节。
支持带有自定义验证器的 JSON 模式
以前,当使用自定义验证器(如 BeforeValidator
或 field_validator
)时,无法自定义与相关字段/类型关联的 mode='validation'
JSON 模式。
现在,您可以使用 json_schema_input_type
规范来自定义具有自定义验证器的字段的 JSON 模式。例如
from typing import Any, Union
from pydantic_core import PydanticKnownError
from typing_extensions import Annotated
from pydantic import PlainValidator, TypeAdapter
def validate_maybe_int(v: Any) -> int:
if isinstance(v, int):
return v
elif isinstance(v, str):
try:
return int(v)
except ValueError:
...
raise PydanticKnownError('int_parsing')
ta = TypeAdapter(Annotated[int, PlainValidator(validate_maybe_int, json_schema_input_type=Union[int, str])])
print(ta.json_schema(mode='validation'))
# > {'anyOf': [{'type': 'integer'}, {'type': 'string'}]}
!!! 注意 您不能将此新功能与 mode='after'
验证器一起使用,因为在此上下文中自定义 mode='validation'
JSON 模式没有意义。
有关实现细节,请参阅 #10094。您可以在所有支持该规范的自定义验证器的 API 文档中找到 json_schema_input_type
的文档。
性能改进
在我们的 v2.9.0 开发周期中,我们非常重视提高 Pydantic 的性能。具体来说,我们对模式构建过程进行了重大改进,从而加快了导入时间并减少了内存分配。
考虑以下用例:您在一个文件中有很多 Pydantic 模型,例如 models.py
。您在另一个文件 main.py
中导入其中一些模型。对于 Pydantic 用户来说,这是一个比较常见的模式。
对于上述情况,我们在导入时间方面实现了高达 10 倍的改进,并且显著减少了临时内存分配,这对拥有大量模型的用户来说是一个巨大的优势。
我们将讨论对模式构建过程进行的一些具体改进。
- 将 pydantic 导入时间减少约 35%,请参阅 #10009 这涵盖了
import pydantic
和from pydantic import BaseModel
等情况。 - 通过优化热循环中的导入来加快模式构建速度约 5%,请参阅 #10013
- 通过跳过命名空间缓存,将模式构建速度(以及内存分配)提高高达 10 倍,请参阅 #10113
- 通过避免命名空间复制操作来减少临时内存分配,请参阅 #10267
我们计划在 v2.10 及更高版本中继续改进模式构建性能。您可以在上述 PR 中找到许多其他详细讨论。
值得注意的改进/修复
标记的 Union
序列化
Pydantic 以其标记联合验证功能而闻名。在 pydantic/pydantic-core#1397 中,我们添加了对标记联合序列化程序的支持,这应该在使用标记联合时做出更直观的序列化决策。我们还进行了一些间接修复,例如改进 float | int
或 Decimal | float
联合的序列化选择。
将注释兼容性错误移动到验证阶段
通常,在模式生成期间,Pydantic 会慷慨地将验证器/约束逻辑应用于类型。这在某些情况下可能会适得其反,因为在运行时,很明显给定的验证器/约束与某些输入数据不兼容。在此版本中,我们为这些情况设计了一些更直观的错误消息,并将它们移动到验证(运行时)阶段,而不是在模式构建时的一些有效情况下失败。有关实现细节,请参阅 #9999
更改
重大更改:合并 dict
类型 json_schema_extra
值,而不是覆盖
此更改不应影响任何内容,除了 `json_schema_extra 的专门用法。话虽如此,如果您想复制旧的行为,请参阅 这些文档。
支持 $ref
键的同级键,从而删除 allOf
JSON 模式解决方法
任何受影响的 JSON 语法现在都是有效的,并且更简单!有关详细信息,请参阅 #10029。
弃用将 dict
传递给 Examples
类
这相对不言自明。有关更多详细信息,请参阅 #10181。此更改鼓励使用语法有效的 JSON 模式。
结论
我们很高兴地宣布 Pydantic v2.9.0 已经发布,它是迄今为止功能最丰富、速度最快的 Pydantic 版本。如果您有任何疑问或反馈,请打开一个 GitHub 讨论。如果您遇到任何错误,请打开一个 GitHub 问题。
感谢我们所有的贡献者使此版本成为可能!我们尤其要感谢以下个人对本次发布做出的重大贡献。
Pydantic Logfire
如果您喜欢 Pydantic,您可能会 非常 喜欢 Pydantic Logfire,这是一种由 Pydantic 背后的团队构建的新可观察性工具。您现在可以 免费试用 Logfire。我们希望您加入 Pydantic Logfire Slack 并告诉我们您的想法!