/发布

Pydantic v2.9

Sydney Runkle avatar
Sydney Runkle
10 分钟

Pydantic v2.9 现已发布!您现在可以通过 PyPI 或您喜欢的包管理器安装它。

pip install --upgrade pydantic

此版本包含 25 多位贡献者的工作成果!在这篇文章中,我们将介绍此版本的亮点。您可以在 GitHub 上查看完整的变更日志。

此版本包含重要的 性能改进联合序列化改进 和一些 新功能

我们已在 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"'

感谢 @changhc 的贡献!有关实现细节,请参阅 #9654

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 设置允许用户指定在从 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 的添加!您可以在 此处 查看完整的实现细节。

以前,当使用自定义验证器(如 BeforeValidatorfield_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 倍的改进,并且显著减少了临时内存分配,这对拥有大量模型的用户来说是一个巨大的优势。

我们将讨论对模式构建过程进行的一些具体改进。

  1. 将 pydantic 导入时间减少约 35%,请参阅 #10009 这涵盖了 import pydanticfrom pydantic import BaseModel 等情况。
  2. 通过优化热循环中的导入来加快模式构建速度约 5%,请参阅 #10013
  3. 通过跳过命名空间缓存,将模式构建速度(以及内存分配)提高高达 10 倍,请参阅 #10113
  4. 通过避免命名空间复制操作来减少临时内存分配,请参阅 #10267

我们计划在 v2.10 及更高版本中继续改进模式构建性能。您可以在上述 PR 中找到许多其他详细讨论。

Pydantic 以其标记联合验证功能而闻名。在 pydantic/pydantic-core#1397 中,我们添加了对标记联合序列化程序的支持,这应该在使用标记联合时做出更直观的序列化决策。我们还进行了一些间接修复,例如改进 float | intDecimal | float 联合的序列化选择。

通常,在模式生成期间,Pydantic 会慷慨地将验证器/约束逻辑应用于类型。这在某些情况下可能会适得其反,因为在运行时,很明显给定的验证器/约束与某些输入数据不兼容。在此版本中,我们为这些情况设计了一些更直观的错误消息,并将它们移动到验证(运行时)阶段,而不是在模式构建时的一些有效情况下失败。有关实现细节,请参阅 #9999

此更改不应影响任何内容,除了 `json_schema_extra 的专门用法。话虽如此,如果您想复制旧的行为,请参阅 这些文档

任何受影响的 JSON 语法现在都是有效的,并且更简单!有关详细信息,请参阅 #10029

这相对不言自明。有关更多详细信息,请参阅 #10181。此更改鼓励使用语法有效的 JSON 模式。

我们很高兴地宣布 Pydantic v2.9.0 已经发布,它是迄今为止功能最丰富、速度最快的 Pydantic 版本。如果您有任何疑问或反馈,请打开一个 GitHub 讨论。如果您遇到任何错误,请打开一个 GitHub 问题

感谢我们所有的贡献者使此版本成为可能!我们尤其要感谢以下个人对本次发布做出的重大贡献。

如果您喜欢 Pydantic,您可能会 非常 喜欢 Pydantic Logfire,这是一种由 Pydantic 背后的团队构建的新可观察性工具。您现在可以 免费试用 Logfire。我们希望您加入 Pydantic Logfire Slack 并告诉我们您的想法!