/发布

Pydantic v2.9

Sydney Runkle avatar
Sydney Runkle
10 分钟

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

pip install --upgrade pydantic

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

此版本包含显著的 性能改进联合序列化改进 以及一些 新功能

我们在 Pydantic 中增加了对 stdlib 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 schema。

现在,您可以使用 json_schema_input_type 规范来自定义带有自定义验证器的字段的 JSON schema。例如

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'}]}

!!! note 您不能将此新功能与 mode='after' 验证器一起使用,因为在此上下文中自定义 mode='validation' JSON schema 没有意义。

有关实现细节,请参阅 #10094。您可以在 API 文档中找到 json_schema_input_type 的文档,适用于所有支持所述规范的自定义验证器。

在 v2.9.0 开发周期中,我们非常重视改进 Pydantic 的性能。具体来说,我们对模式构建过程进行了重大改进,从而加快了导入速度并减少了内存分配。

考虑以下用例:您在一个文件中(例如 models.py)有大量 Pydantic 模型。您在另一个文件 (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 schema。

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

感谢所有为实现此版本做出贡献的贡献者!我们特别要感谢以下个人为此次发布做出的重大贡献

如果您喜欢 Pydantic,您可能会非常喜欢 Pydantic Logfire,这是 Pydantic 团队构建的全新可观测性工具。您现在可以 试用 Logfire 免费版。如果您能加入 Pydantic Logfire Slack 并告诉我们您的想法,我们将不胜感激!