使用错误
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 Schema¶
__modify_schema__
方法在 V2 中不再支持。您应该改用 __get_pydantic_json_schema__
方法。
__modify_schema__
曾经接收一个表示 JSON schema 的参数。请参见下面的示例
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 schema。请参见下面的示例
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_a(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 Schema 无效类型¶
当 Pydantic 无法为某个 CoreSchema
生成 JSON Schema 时,会引发此错误。
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 Schema 已使用¶
当 JSON Schema 生成器已用于生成 JSON Schema 时,会引发此错误。您必须创建新实例才能生成新的 JSON Schema。
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'
未知类型的 Schema¶
当 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'
字段定义语法可在动态模型创建文档中找到。
无字段的验证器¶
当您裸用验证器(无字段)时,会引发此错误。
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 Schema 输入类型。这就是为什么它不适用于 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
一起使用¶
如果您尝试将 config
传递给 TypeAdapter
,而类型是具有其自身配置且无法覆盖的类型(目前仅为 BaseModel
、TypedDict
和 dataclass
),您将收到此错误
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
不能将 model_config['extra']
与 RootModel
一起指定¶
由于 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 构建 Schema 期间导致以下错误
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'