使用错误
Pydantic 致力于提供有用的错误信息。以下部分详细介绍了开发人员在使用 Pydantic 时可能遇到的常见错误,以及解决这些错误情况的建议。
类未完全定义¶
当在 pydantic 验证类型(例如 BaseModel 的子类或 pydantic dataclass)的注解中引用的类型未定义时,会引发此错误:
from typing import ForwardRef
from pydantic import BaseModel, PydanticUserError
UndefinedType = ForwardRef('UndefinedType')
class Foobar(BaseModel):
a: UndefinedType
try:
Foobar(a=1)
except PydanticUserError as exc_info:
assert exc_info.code == 'class-not-fully-defined'
或者在类型在使用之后才定义的情况下:
from typing import Optional
from pydantic import BaseModel, PydanticUserError
class Foo(BaseModel):
a: Optional['Bar'] = None
try:
# this doesn't work, see raised error
foo = Foo(a={'b': {'a': None}})
except PydanticUserError as exc_info:
assert exc_info.code == 'class-not-fully-defined'
class Bar(BaseModel):
b: 'Foo'
# this works, though
foo = Foo(a={'b': {'a': None}})
对于 BaseModel 子类,可以通过定义类型然后调用 .model_rebuild() 来修复:
from typing import Optional
from pydantic import BaseModel
class Foo(BaseModel):
a: Optional['Bar'] = None
class Bar(BaseModel):
b: 'Foo'
Foo.model_rebuild()
foo = Foo(a={'b': {'a': None}})
在其他情况下,错误消息应指示如何使用定义好的适当类型来重建类。
自定义 JSON 模式¶
V2 版本中不再支持 __modify_schema__ 方法。你应该改用 __get_pydantic_json_schema__ 方法。
__modify_schema__ 过去接收一个代表 JSON 模式的参数。参见以下示例:
from pydantic import BaseModel, PydanticUserError
try:
class Model(BaseModel):
@classmethod
def __modify_schema__(cls, field_schema):
field_schema.update(examples=['example'])
except PydanticUserError as exc_info:
assert exc_info.code == 'custom-json-schema'
新方法 __get_pydantic_json_schema__ 接收两个参数:第一个是表示为 CoreSchema 的字典,第二个是一个可调用的 handler,它接收一个 CoreSchema 作为参数,并返回一个 JSON 模式。参见以下示例:
from typing import Any
from pydantic_core import CoreSchema
from pydantic import BaseModel, GetJsonSchemaHandler
class Model(BaseModel):
@classmethod
def __get_pydantic_json_schema__(
cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler
) -> dict[str, Any]:
json_schema = super().__get_pydantic_json_schema__(core_schema, handler)
json_schema = handler.resolve_ref_schema(json_schema)
json_schema.update(examples=['example'])
return json_schema
print(Model.model_json_schema())
"""
{'examples': ['example'], 'properties': {}, 'title': 'Model', 'type': 'object'}
"""
装饰器应用于缺失字段¶
当你定义一个使用了无效字段的装饰器时,会引发此错误。
from typing import Any
from pydantic import BaseModel, PydanticUserError, field_validator
try:
class Model(BaseModel):
a: str
@field_validator('b')
def check_b(cls, v: Any):
return v
except PydanticUserError as exc_info:
assert exc_info.code == 'decorator-missing-field'
如果你是从模型继承并有意如此,可以使用 check_fields=False。
from typing import Any
from pydantic import BaseModel, create_model, field_validator
class Model(BaseModel):
@field_validator('a', check_fields=False)
def check cls, v: Any):
return v
model = create_model('FooModel', a=(str, 'cake'), __base__=Model)
鉴别器无字段¶
当受歧视联合中的模型未定义鉴别器字段时,会引发此错误。
from typing import Literal, Union
from pydantic import BaseModel, Field, PydanticUserError
class Cat(BaseModel):
c: str
class Dog(BaseModel):
pet_type: Literal['dog']
d: str
try:
class Model(BaseModel):
pet: Union[Cat, Dog] = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-no-field'
from typing import Literal
from pydantic import BaseModel, Field, PydanticUserError
class Cat(BaseModel):
c: str
class Dog(BaseModel):
pet_type: Literal['dog']
d: str
try:
class Model(BaseModel):
pet: Cat | Dog = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-no-field'
鉴别器别名类型¶
当你在鉴别器字段上定义非字符串别名时,会引发此错误。
from typing import Literal, Union
from pydantic import AliasChoices, BaseModel, Field, PydanticUserError
class Cat(BaseModel):
pet_type: Literal['cat'] = Field(
validation_alias=AliasChoices('Pet', 'PET')
)
c: str
class Dog(BaseModel):
pet_type: Literal['dog']
d: str
try:
class Model(BaseModel):
pet: Union[Cat, Dog] = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-alias-type'
from typing import Literal
from pydantic import AliasChoices, BaseModel, Field, PydanticUserError
class Cat(BaseModel):
pet_type: Literal['cat'] = Field(
validation_alias=AliasChoices('Pet', 'PET')
)
c: str
class Dog(BaseModel):
pet_type: Literal['dog']
d: str
try:
class Model(BaseModel):
pet: Cat | Dog = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-alias-type'
鉴别器需要字面量¶
当你在鉴别器字段上定义非 Literal 类型时,会引发此错误。
from typing import Literal, Union
from pydantic import BaseModel, Field, PydanticUserError
class Cat(BaseModel):
pet_type: int
c: str
class Dog(BaseModel):
pet_type: Literal['dog']
d: str
try:
class Model(BaseModel):
pet: Union[Cat, Dog] = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-needs-literal'
from typing import Literal
from pydantic import BaseModel, Field, PydanticUserError
class Cat(BaseModel):
pet_type: int
c: str
class Dog(BaseModel):
pet_type: Literal['dog']
d: str
try:
class Model(BaseModel):
pet: Cat | Dog = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-needs-literal'
鉴别器别名¶
当你在鉴别器字段上定义不同的别名时,会引发此错误。
from typing import Literal, Union
from pydantic import BaseModel, Field, PydanticUserError
class Cat(BaseModel):
pet_type: Literal['cat'] = Field(validation_alias='PET')
c: str
class Dog(BaseModel):
pet_type: Literal['dog'] = Field(validation_alias='Pet')
d: str
try:
class Model(BaseModel):
pet: Union[Cat, Dog] = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-alias'
from typing import Literal
from pydantic import BaseModel, Field, PydanticUserError
class Cat(BaseModel):
pet_type: Literal['cat'] = Field(validation_alias='PET')
c: str
class Dog(BaseModel):
pet_type: Literal['dog'] = Field(validation_alias='Pet')
d: str
try:
class Model(BaseModel):
pet: Cat | Dog = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-alias'
无效的鉴别器验证器¶
当你在鉴别器字段上使用 before、wrap 或 plain 验证器时,会引发此错误。
这是不允许的,因为鉴别器字段用于确定用于验证的模型类型,因此你不能使用可能改变其值的验证器。
from typing import Literal, Union
from pydantic import BaseModel, Field, PydanticUserError, field_validator
class Cat(BaseModel):
pet_type: Literal['cat']
@field_validator('pet_type', mode='before')
@classmethod
def validate_pet_type(cls, v):
if v == 'kitten':
return 'cat'
return v
class Dog(BaseModel):
pet_type: Literal['dog']
try:
class Model(BaseModel):
pet: Union[Cat, Dog] = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-validator'
from typing import Literal
from pydantic import BaseModel, Field, PydanticUserError, field_validator
class Cat(BaseModel):
pet_type: Literal['cat']
@field_validator('pet_type', mode='before')
@classmethod
def validate_pet_type(cls, v):
if v == 'kitten':
return 'cat'
return v
class Dog(BaseModel):
pet_type: Literal['dog']
try:
class Model(BaseModel):
pet: Cat | Dog = Field(discriminator='pet_type')
number: int
except PydanticUserError as exc_info:
assert exc_info.code == 'discriminator-validator'
可以通过使用标准的 Union 并放弃鉴别器来解决此问题:
from typing import Literal, Union
from pydantic import BaseModel, field_validator
class Cat(BaseModel):
pet_type: Literal['cat']
@field_validator('pet_type', mode='before')
@classmethod
def validate_pet_type(cls, v):
if v == 'kitten':
return 'cat'
return v
class Dog(BaseModel):
pet_type: Literal['dog']
class Model(BaseModel):
pet: Union[Cat, Dog]
assert Model(pet={'pet_type': 'kitten'}).pet.pet_type == 'cat'
from typing import Literal
from pydantic import BaseModel, field_validator
class Cat(BaseModel):
pet_type: Literal['cat']
@field_validator('pet_type', mode='before')
@classmethod
def validate_pet_type(cls, v):
if v == 'kitten':
return 'cat'
return v
class Dog(BaseModel):
pet_type: Literal['dog']
class Model(BaseModel):
pet: Cat | Dog
assert Model(pet={'pet_type': 'kitten'}).pet.pet_type == 'cat'
可调用鉴别器情况无标签¶
当使用可调用 Discriminator 的 Union 没有为所有情况提供 Tag 注解时,会引发此错误。
from typing import Annotated, Union
from pydantic import BaseModel, Discriminator, PydanticUserError, Tag
def model_x_discriminator(v):
if isinstance(v, str):
return 'str'
if isinstance(v, (dict, BaseModel)):
return 'model'
# tag missing for both union choices
try:
class DiscriminatedModel(BaseModel):
x: Annotated[
Union[str, 'DiscriminatedModel'],
Discriminator(model_x_discriminator),
]
except PydanticUserError as exc_info:
assert exc_info.code == 'callable-discriminator-no-tag'
# tag missing for `'DiscriminatedModel'` union choice
try:
class DiscriminatedModel(BaseModel):
x: Annotated[
Union[Annotated[str, Tag('str')], 'DiscriminatedModel'],
Discriminator(model_x_discriminator),
]
except PydanticUserError as exc_info:
assert exc_info.code == 'callable-discriminator-no-tag'
# tag missing for `str` union choice
try:
class DiscriminatedModel(BaseModel):
x: Annotated[
Union[str, Annotated['DiscriminatedModel', Tag('model')]],
Discriminator(model_x_discriminator),
]
except PydanticUserError as exc_info:
assert exc_info.code == 'callable-discriminator-no-tag'
from typing import Annotated, Union
from pydantic import BaseModel, Discriminator, PydanticUserError, Tag
def model_x_discriminator(v):
if isinstance(v, str):
return 'str'
if isinstance(v, (dict, BaseModel)):
return 'model'
# tag missing for both union choices
try:
class DiscriminatedModel(BaseModel):
x: Annotated[
Union[str, 'DiscriminatedModel'],
Discriminator(model_x_discriminator),
]
except PydanticUserError as exc_info:
assert exc_info.code == 'callable-discriminator-no-tag'
# tag missing for `'DiscriminatedModel'` union choice
try:
class DiscriminatedModel(BaseModel):
x: Annotated[
Union[Annotated[str, Tag('str')], 'DiscriminatedModel'],
Discriminator(model_x_discriminator),
]
except PydanticUserError as exc_info:
assert exc_info.code == 'callable-discriminator-no-tag'
# tag missing for `str` union choice
try:
class DiscriminatedModel(BaseModel):
x: Annotated[
str | Annotated['DiscriminatedModel', Tag('model')],
Discriminator(model_x_discriminator),
]
except PydanticUserError as exc_info:
assert exc_info.code == 'callable-discriminator-no-tag'
TypedDict 版本¶
当你在 Python < 3.12 上使用 typing.TypedDict 而不是 typing_extensions.TypedDict 时,会引发此错误。
模型父字段被覆盖¶
当基类上定义的字段被非注解属性覆盖时,会引发此错误。
from pydantic import BaseModel, PydanticUserError
class Foo(BaseModel):
a: float
try:
class Bar(Foo):
x: float = 12.3
a = 123.0
except PydanticUserError as exc_info:
assert exc_info.code == 'model-field-overridden'
模型字段缺失注解¶
当字段没有注解时,会引发此错误。
from pydantic import BaseModel, Field, PydanticUserError
try:
class Model(BaseModel):
a = Field('foobar')
b = None
except PydanticUserError as exc_info:
assert exc_info.code == 'model-field-missing-annotation'
如果该字段不是作为字段使用,你可以通过将其注解为 ClassVar 来解决错误:
from typing import ClassVar
from pydantic import BaseModel
class Model(BaseModel):
a: ClassVar[str]
或者更新 model_config['ignored_types']:
from pydantic import BaseModel, ConfigDict
class IgnoredType:
pass
class MyModel(BaseModel):
model_config = ConfigDict(ignored_types=(IgnoredType,))
_a = IgnoredType()
_b: int = IgnoredType()
_c: IgnoredType
_d: IgnoredType = IgnoredType()
Config 和 model_config 同时定义¶
当 class Config 和 model_config 同时使用时,会引发此错误。
from pydantic import BaseModel, ConfigDict, PydanticUserError
try:
class Model(BaseModel):
model_config = ConfigDict(from_attributes=True)
a: str
class Config:
from_attributes = True
except PydanticUserError as exc_info:
assert exc_info.code == 'config-both'
关键字参数已移除¶
当关键字参数在 Pydantic V2 中不可用时,会引发此错误。
例如,regex 已从 Pydantic V2 中移除:
from pydantic import BaseModel, Field, PydanticUserError
try:
class Model(BaseModel):
x: str = Field(regex='test')
except PydanticUserError as exc_info:
assert exc_info.code == 'removed-kwargs'
循环引用模式¶
当发现循环引用可能导致无限递归时,会引发此错误。
例如,这是一个有效的类型别名:
type A = list[A] | None
而这些不是:
type A = A
type B = C
type C = B
JSON 模式无效类型¶
当 Pydantic 无法为某些 CoreSchema 生成 JSON 模式时,会引发此错误。
from pydantic import BaseModel, ImportString, PydanticUserError
class Model(BaseModel):
a: ImportString
try:
Model.model_json_schema()
except PydanticUserError as exc_info:
assert exc_info.code == 'invalid-for-json-schema'
JSON 模式已使用¶
当 JSON 模式生成器已被用于生成 JSON 模式时,会引发此错误。 你必须创建一个新实例来生成新的 JSON 模式。
BaseModel 已实例化¶
当你直接实例化 BaseModel 时,会引发此错误。Pydantic 模型应该继承自 BaseModel。
from pydantic import BaseModel, PydanticUserError
try:
BaseModel()
except PydanticUserError as exc_info:
assert exc_info.code == 'base-model-instantiated'
未定义的注解¶
在 CoreSchema 生成过程中处理未定义的注解时,会引发此错误。
from pydantic import BaseModel, PydanticUndefinedAnnotation
class Model(BaseModel):
a: 'B' # noqa F821
try:
Model.model_rebuild()
except PydanticUndefinedAnnotation as exc_info:
assert exc_info.code == 'undefined-annotation'
未知类型的模式¶
当 Pydantic 无法为某些类型生成 CoreSchema 时,会引发此错误。
from pydantic import BaseModel, PydanticUserError
try:
class Model(BaseModel):
x: 43 = 123
except PydanticUserError as exc_info:
assert exc_info.code == 'schema-for-unknown-type'
导入错误¶
当你尝试导入在 Pydantic V1 中可用但在 Pydantic V2 中已被移除的对象时,会引发此错误。
更多信息请参阅 迁移指南。
create_model 字段定义¶
当你在 create_model() 中提供无效的字段定义时,会引发此错误。
from pydantic import PydanticUserError, create_model
try:
create_model('FooModel', foo=(str, 'default value', 'more'))
except PydanticUserError as exc_info:
assert exc_info.code == 'create-model-field-definitions'
字段定义语法可以在 动态模型创建 文档中找到。
验证器无字段¶
当你使用无字段的验证器(bare validator)时,会引发此错误。
from pydantic import BaseModel, PydanticUserError, field_validator
try:
class Model(BaseModel):
a: str
@field_validator
def checker(cls, v):
return v
except PydanticUserError as exc_info:
assert exc_info.code == 'validator-no-fields'
验证器应该与字段和关键字参数一起使用。
from pydantic import BaseModel, field_validator
class Model(BaseModel):
a: str
@field_validator('a')
def checker(cls, v):
return v
无效的验证器字段¶
当你使用带有非字符串字段的验证器时,会引发此错误。
from pydantic import BaseModel, PydanticUserError, field_validator
try:
class Model(BaseModel):
a: str
b: str
@field_validator(['a', 'b'])
def check_fields(cls, v):
return v
except PydanticUserError as exc_info:
assert exc_info.code == 'validator-invalid-fields'
字段应作为单独的字符串参数传递:
from pydantic import BaseModel, field_validator
class Model(BaseModel):
a: str
b: str
@field_validator('a', 'b')
def check_fields(cls, v):
return v
实例方法上的验证器¶
当你将验证器应用于实例方法时,会引发此错误。
from pydantic import BaseModel, PydanticUserError, field_validator
try:
class Model(BaseModel):
a: int = 1
@field_validator('a')
def check_a(self, value):
return value
except PydanticUserError as exc_info:
assert exc_info.code == 'validator-instance-method'
json_schema_input_type 与错误的模式一起使用¶
当你为 json_schema_input_type 参数显式指定一个值,并且 mode 未设置为 'before'、'plain' 或 'wrap' 之一时,会引发此错误。
from pydantic import BaseModel, PydanticUserError, field_validator
try:
class Model(BaseModel):
a: int = 1
@field_validator('a', mode='after', json_schema_input_type=int)
@classmethod
def check_a(self, value):
return value
except PydanticUserError as exc_info:
assert exc_info.code == 'validator-input-type'
记录 JSON 模式输入类型仅适用于给定值可以是任何内容的验证器。这就是为什么它不适用于 after 验证器,因为该值首先会根据类型注解进行验证。
根验证器,pre,skip_on_failure¶
如果你使用 @root_validator 且 pre=False(默认值),则必须指定 skip_on_failure=True。
skip_on_failure=False 选项不再可用。
如果你并未尝试设置 skip_on_failure=False,你可以安全地设置 skip_on_failure=True。
如果这样做,则当任何字段验证失败时,将不再调用此根验证器。
更多详情请参阅 迁移指南。
model_serializer 实例方法¶
@model_serializer 必须应用于实例方法。
当你在没有 self 的实例方法上应用 model_serializer 时,会引发此错误:
from pydantic import BaseModel, PydanticUserError, model_serializer
try:
class MyModel(BaseModel):
a: int
@model_serializer
def _serialize(slf, x, y, z):
return slf
except PydanticUserError as exc_info:
assert exc_info.code == 'model-serializer-instance-method'
或者在类方法上:
from pydantic import BaseModel, PydanticUserError, model_serializer
try:
class MyModel(BaseModel):
a: int
@model_serializer
@classmethod
def _serialize(self, x, y, z):
return self
except PydanticUserError as exc_info:
assert exc_info.code == 'model-serializer-instance-method'
validator,field,config,和 info¶
field 和 config 参数在 Pydantic V2 中不可用。
请改用 info 参数。
你可以通过 info.config 访问配置,但它是一个字典,而不是像 Pydantic V1 中那样的对象。
field 参数不再可用。
Pydantic V1 验证器签名¶
当你使用 Pydantic V1 风格验证器的不支持签名时,会引发此错误。
import warnings
from pydantic import BaseModel, PydanticUserError, validator
warnings.filterwarnings('ignore', category=DeprecationWarning)
try:
class Model(BaseModel):
a: int
@validator('a')
def check_a(cls, value, foo):
return value
except PydanticUserError as exc_info:
assert exc_info.code == 'validator-v1-signature'
无法识别的 field_validator 签名¶
当 field_validator 或 model_validator 函数的签名错误时,会引发此错误。
from pydantic import BaseModel, PydanticUserError, field_validator
try:
class Model(BaseModel):
a: str
@field_validator('a')
@classmethod
def check_a(cls):
return 'a'
except PydanticUserError as exc_info:
assert exc_info.code == 'validator-signature'
无法识别的 field_serializer 签名¶
当 field_serializer 函数的签名错误时,会引发此错误。
from pydantic import BaseModel, PydanticUserError, field_serializer
try:
class Model(BaseModel):
x: int
@field_serializer('x')
def no_args():
return 'x'
except PydanticUserError as exc_info:
assert exc_info.code == 'field-serializer-signature'
有效的字段序列化器签名是:
from pydantic import FieldSerializationInfo, SerializerFunctionWrapHandler, field_serializer
# an instance method with the default mode or `mode='plain'`
@field_serializer('x') # or @field_serializer('x', mode='plain')
def ser_x(self, value: Any, info: FieldSerializationInfo): ...
# a static method or function with the default mode or `mode='plain'`
@field_serializer('x') # or @field_serializer('x', mode='plain')
@staticmethod
def ser_x(value: Any, info: FieldSerializationInfo): ...
# equivalent to
def ser_x(value: Any, info: FieldSerializationInfo): ...
serializer('x')(ser_x)
# an instance method with `mode='wrap'`
@field_serializer('x', mode='wrap')
def ser_x(self, value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo): ...
# a static method or function with `mode='wrap'`
@field_serializer('x', mode='wrap')
@staticmethod
def ser_x(value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo): ...
# equivalent to
def ser_x(value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo): ...
serializer('x')(ser_x)
# For all of these, you can also choose to omit the `info` argument, for example:
@field_serializer('x')
def ser_x(self, value: Any): ...
@field_serializer('x', mode='wrap')
def ser_x(self, value: Any, handler: SerializerFunctionWrapHandler): ...
无法识别的 model_serializer 签名¶
当 model_serializer 函数的签名错误时,会引发此错误。
from pydantic import BaseModel, PydanticUserError, model_serializer
try:
class MyModel(BaseModel):
a: int
@model_serializer
def _serialize(self, x, y, z):
return self
except PydanticUserError as exc_info:
assert exc_info.code == 'model-serializer-signature'
有效的模型序列化器签名是:
from pydantic import SerializerFunctionWrapHandler, SerializationInfo, model_serializer
# an instance method with the default mode or `mode='plain'`
@model_serializer # or model_serializer(mode='plain')
def mod_ser(self, info: SerializationInfo): ...
# an instance method with `mode='wrap'`
@model_serializer(mode='wrap')
def mod_ser(self, handler: SerializerFunctionWrapHandler, info: SerializationInfo):
# For all of these, you can also choose to omit the `info` argument, for example:
@model_serializer(mode='plain')
def mod_ser(self): ...
@model_serializer(mode='wrap')
def mod_ser(self, handler: SerializerFunctionWrapHandler): ...
多个字段序列化器¶
当为字段定义了多个 model_serializer 函数时,会引发此错误。
from pydantic import BaseModel, PydanticUserError, field_serializer
try:
class MyModel(BaseModel):
x: int
y: int
@field_serializer('x', 'y')
def serializer1(v):
return f'{v:,}'
@field_serializer('x')
def serializer2(v):
return v
except PydanticUserError as exc_info:
assert exc_info.code == 'multiple-field-serializers'
无效的注解类型¶
当注解无法注解类型时,会引发此错误。
from typing import Annotated
from pydantic import BaseModel, FutureDate, PydanticUserError
try:
class Model(BaseModel):
foo: Annotated[str, FutureDate()]
except PydanticUserError as exc_info:
assert exc_info.code == 'invalid-annotated-type'
config 与 TypeAdapter 一起使用时未使用¶
如果你尝试在类型是具有无法被覆盖的自身配置的类型(目前只有 BaseModel、TypedDict 和 dataclass)时向 TypeAdapter 传递 config,你会收到此错误:
from typing_extensions import TypedDict
from pydantic import ConfigDict, PydanticUserError, TypeAdapter
class MyTypedDict(TypedDict):
x: int
try:
TypeAdapter(MyTypedDict, config=ConfigDict(strict=True))
except PydanticUserError as exc_info:
assert exc_info.code == 'type-adapter-config-unused'
from typing import TypedDict
from pydantic import ConfigDict, PydanticUserError, TypeAdapter
class MyTypedDict(TypedDict):
x: int
try:
TypeAdapter(MyTypedDict, config=ConfigDict(strict=True))
except PydanticUserError as exc_info:
assert exc_info.code == 'type-adapter-config-unused'
相反,你需要子类化该类型并在其上覆盖或设置配置:
from typing_extensions import TypedDict
from pydantic import ConfigDict, TypeAdapter
class MyTypedDict(TypedDict):
x: int
# or `model_config = ...` for BaseModel
__pydantic_config__ = ConfigDict(strict=True)
TypeAdapter(MyTypedDict) # ok
from typing import TypedDict
from pydantic import ConfigDict, TypeAdapter
class MyTypedDict(TypedDict):
x: int
# or `model_config = ...` for BaseModel
__pydantic_config__ = ConfigDict(strict=True)
TypeAdapter(MyTypedDict) # ok
无法使用 RootModel 指定 model_config['extra']¶
因为 RootModel 无法在初始化期间存储甚至接受额外字段,如果你尝试在创建 RootModel 子类时为配置设置 'extra' 指定值,我们会引发错误:
from pydantic import PydanticUserError, RootModel
try:
class MyRootModel(RootModel):
model_config = {'extra': 'allow'}
root: int
except PydanticUserError as exc_info:
assert exc_info.code == 'root-model-extra'
无法评估类型注解¶
因为类型注解是在赋值之后评估的,当你使用与某个字段名称冲突的类型注解名称时,可能会得到意想不到的结果。我们在以下情况下引发错误:
from datetime import date
from pydantic import BaseModel, Field
class Model(BaseModel):
date: date = Field(description='A date')
作为变通方法,你可以使用别名或更改你的导入:
import datetime
# Or `from datetime import date as _date`
from pydantic import BaseModel, Field
class Model(BaseModel):
date: datetime.date = Field(description='A date')
不兼容的 dataclass init 和 extra 设置¶
Pydantic 不允许在 dataclass 上指定 extra='allow' 设置,而任何字段设置了 init=False。
因此,你可能无法执行如下操作:
from pydantic import ConfigDict, Field
from pydantic.dataclasses import dataclass
@dataclass(config=ConfigDict(extra='allow'))
class A:
a: int = Field(init=False, default=1)
上面的代码片段在构建 A dataclass 的模式期间会导致以下错误:
pydantic.errors.PydanticUserError: Field a has `init=False` and dataclass has config setting `extra="allow"`.
This combination is not allowed.
dataclass 字段上不兼容的 init 和 init_var 设置¶
init=False 和 init_var=True 设置是互斥的。这样做会导致如下例所示的 PydanticUserError。
from pydantic import Field
from pydantic.dataclasses import dataclass
@dataclass
class Foo:
bar: str = Field(init=False, init_var=True)
"""
pydantic.errors.PydanticUserError: Dataclass field bar has init=False and init_var=True, but these are mutually exclusive.
"""
model_config 被用作模型字段¶
当 model_config 被用作字段名称时,会引发此错误。
from pydantic import BaseModel, PydanticUserError
try:
class Model(BaseModel):
model_config: str
except PydanticUserError as exc_info:
assert exc_info.code == 'model-config-invalid-field-name'
with_config 用于 BaseModel 子类¶
当 with_config 装饰器用于已经是 Pydantic 模型的类时,会引发此错误(请改用 model_config 属性)。
from pydantic import BaseModel, PydanticUserError, with_config
try:
@with_config({'allow_inf_nan': True})
class Model(BaseModel):
bar: str
except PydanticUserError as exc_info:
assert exc_info.code == 'with-config-on-model'
dataclass 用于 BaseModel 子类¶
当 Pydantic dataclass 装饰器用于已经是 Pydantic 模型的类时,会引发此错误。
from pydantic import BaseModel, PydanticUserError
from pydantic.dataclasses import dataclass
try:
@dataclass
class Model(BaseModel):
bar: str
except PydanticUserError as exc_info:
assert exc_info.code == 'dataclass-on-model'
validate_call 不支持的类型¶
validate_call 对其可以验证的可调用对象有一些限制。当你尝试将其与不支持的可调用对象一起使用时,会引发此错误。
当前支持的可调用对象是函数(包括 lambda,但不包括内置函数)和方法以及 partial 的实例。
在 partial 的情况下,被部分应用的函数必须是受支持的可调用对象之一。
@classmethod,@staticmethod,和 @property¶
这些装饰器必须放在 validate_call 之前。
from pydantic import PydanticUserError, validate_call
# error
try:
class A:
@validate_call
@classmethod
def f1(cls): ...
except PydanticUserError as exc_info:
assert exc_info.code == 'validate-call-type'
# correct
@classmethod
@validate_call
def f2(cls): ...
类¶
虽然类本身是可调用的,但 validate_call 不能应用于它们,因为它需要知道使用哪个方法(__init__ 或 __new__)来获取类型注解。如果你想验证类的构造函数,你应该将 validate_call 放在相应的方法上。
from pydantic import PydanticUserError, validate_call
# error
try:
@validate_call
class A1: ...
except PydanticUserError as exc_info:
assert exc_info.code == 'validate-call-type'
# correct
class A2:
@validate_call
def __init__(self): ...
@validate_call
def __new__(cls): ...
可调用实例¶
虽然实例可以通过实现 __call__ 方法变得可调用,但目前这些类型的实例无法用 validate_call 验证。
这可能会在未来改变,但目前,你应该在 __call__ 上显式使用 validate_call。
from pydantic import PydanticUserError, validate_call
# error
try:
class A1:
def __call__(self): ...
validate_call(A1())
except PydanticUserError as exc_info:
assert exc_info.code == 'validate-call-type'
# correct
class A2:
@validate_call
def __call__(self): ...
无效签名¶
这通常较少见,但一个可能的原因是你试图验证一个没有至少一个参数(通常是 self)的方法。
from pydantic import PydanticUserError, validate_call
try:
class A:
def f(): ...
validate_call(A().f)
except PydanticUserError as exc_info:
assert exc_info.code == 'validate-call-type'
Unpack 未与 TypedDict 一起使用¶
当 Unpack 与 TypedDict 类对象以外的内容一起使用来类型提示可变关键字参数时,会引发此错误。
from typing_extensions import Unpack
from pydantic import PydanticUserError, validate_call
try:
@validate_call
def func(**kwargs: Unpack[int]):
pass
except PydanticUserError as exc_info:
assert exc_info.code == 'unpack-typed-dict'
from typing import Unpack
from pydantic import PydanticUserError, validate_call
try:
@validate_call
def func(**kwargs: Unpack[int]):
pass
except PydanticUserError as exc_info:
assert exc_info.code == 'unpack-typed-dict'
重叠的解包 TypedDict 字段和参数¶
当用于类型提示可变关键字参数的类型字典的字段名称与其他参数重叠时(除非是 仅位置参数),会引发此错误。
from typing_extensions import TypedDict, Unpack
from pydantic import PydanticUserError, validate_call
class TD(TypedDict):
a: int
try:
@validate_call
def func(a: int, **kwargs: Unpack[TD]):
pass
except PydanticUserError as exc_info:
assert exc_info.code == 'overlapping-unpack-typed-dict'
from typing_extensions import TypedDict
from typing import Unpack
from pydantic import PydanticUserError, validate_call
class TD(TypedDict):
a: int
try:
@validate_call
def func(a: int, **kwargs: Unpack[TD]):
pass
except PydanticUserError as exc_info:
assert exc_info.code == 'overlapping-unpack-typed-dict'
from typing import TypedDict, Unpack
from pydantic import PydanticUserError, validate_call
class TD(TypedDict):
a: int
try:
@validate_call
def func(a: int, **kwargs: Unpack[TD]):
pass
except PydanticUserError as exc_info:
assert exc_info.code == 'overlapping-unpack-typed-dict'
无效的 Self 类型¶
目前,Self 只能用于注解类的字段(特别是 BaseModel、NamedTuple、TypedDict 或 dataclasses 的子类)。尝试以任何其他方式使用 Self 都会引发此错误。
from typing_extensions import Self
from pydantic import PydanticUserError, validate_call
try:
@validate_call
def func(self: Self):
pass
except PydanticUserError as exc_info:
assert exc_info.code == 'invalid-self-type'
from typing import Self
from pydantic import PydanticUserError, validate_call
try:
@validate_call
def func(self: Self):
pass
except PydanticUserError as exc_info:
assert exc_info.code == 'invalid-self-type'
以下 validate_call() 的示例也会引发此错误,即使从类型检查的角度来看它是正确的。这可能会在未来得到支持。
from typing_extensions import Self
from pydantic import BaseModel, PydanticUserError, validate_call
try:
class A(BaseModel):
@validate_call
def func(self, arg: Self):
pass
except PydanticUserError as exc_info:
assert exc_info.code == 'invalid-self-type'
from typing import Self
from pydantic import BaseModel, PydanticUserError, validate_call
try:
class A(BaseModel):
@validate_call
def func(self, arg: Self):
pass
except PydanticUserError as exc_info:
assert exc_info.code == 'invalid-self-type'
validate_by_alias 和 validate_by_name 都设置为 False¶
当你在配置中将 validate_by_alias 和 validate_by_name 都设置为 False 时,会引发此错误。
这是不允许的,因为它将使得无法填充属性。
from pydantic import BaseModel, ConfigDict, Field, PydanticUserError
try:
class Model(BaseModel):
a: int = Field(alias='A')
model_config = ConfigDict(
validate_by_alias=False, validate_by_name=False
)
except PydanticUserError as exc_info:
assert exc_info.code == 'validate-by-alias-and-name-false'