エラー処理
Pydantic は、検証中のデータにエラーが見つかると必ず ValidationError
を発生させます。
!!! note 検証コードはValidationError
自体を発生させるのではなく、捕捉されてValidationError
を設定するために使用されるValueError
またはAssertionError
(またはそのサブクラス) を発生させる必要があります。
見つかったエラーの数に関係なく 1 つの例外が発生します。そのValidationError
は、すべてのエラーとその発生方法に関する情報が含まれています。
これらのエラーにはいくつかの方法でアクセスできます。
方法 | 説明 |
---|---|
e.errors() | 入力データ内で見つかったエラーのリストを返します。 |
e.error_count() | errors で見つかったエラーの数を返します。 |
e.json() | errors の JSON 表現を返します。 |
str(e) | 人間が判読できるエラー表現を返します。 |
各エラー オブジェクトには次のものが含まれます。
財産 | 説明 |
---|---|
ctx | エラー メッセージを表示するために必要な値を含むオプションのオブジェクト。 |
input | 検証のために提供された入力。 |
loc | エラーの場所をリストとして表示します。 |
msg | 人間が読めるエラーの説明。 |
type | コンピューターが読み取り可能なエラーの種類の識別子。 |
url | エラーに関する詳細情報への URL。 |
loc
リストの最初の項目は、エラーが発生したフィールドになります。フィールドがサブモデルの場合、後続の項目は、エラーのネストされた位置を示すために存在します。
デモンストレーションとして:
from typing import List
from pydantic import BaseModel, ValidationError, conint
class Location(BaseModel):
lat: float = 0.1
lng: float = 10.1
class Model(BaseModel):
is_required: float
gt_int: conint(gt=42)
list_of_ints: List[int] = None
a_float: float = None
recursive_model: Location = None
data = dict(
list_of_ints=['1', 2, 'bad'],
a_float='not a float',
recursive_model={'lat': 4.2, 'lng': 'New York'},
gt_int=21,
)
try:
Model(**data)
except ValidationError as e:
print(e)
"""
5 validation errors for Model
is_required
Field required [type=missing, input_value={'list_of_ints': ['1', 2,...ew York'}, 'gt_int': 21}, input_type=dict]
gt_int
Input should be greater than 42 [type=greater_than, input_value=21, input_type=int]
list_of_ints.2
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='bad', input_type=str]
a_float
Input should be a valid number, unable to parse string as a number [type=float_parsing, input_value='not a float', input_type=str]
recursive_model.lng
Input should be a valid number, unable to parse string as a number [type=float_parsing, input_value='New York', input_type=str]
"""
try:
Model(**data)
except ValidationError as e:
print(e.errors())
"""
[
{
'type': 'missing',
'loc': ('is_required',),
'msg': 'Field required',
'input': {
'list_of_ints': ['1', 2, 'bad'],
'a_float': 'not a float',
'recursive_model': {'lat': 4.2, 'lng': 'New York'},
'gt_int': 21,
},
'url': 'https://errors.pydantic.dev/2/v/missing',
},
{
'type': 'greater_than',
'loc': ('gt_int',),
'msg': 'Input should be greater than 42',
'input': 21,
'ctx': {'gt': 42},
'url': 'https://errors.pydantic.dev/2/v/greater_than',
},
{
'type': 'int_parsing',
'loc': ('list_of_ints', 2),
'msg': 'Input should be a valid integer, unable to parse string as an integer',
'input': 'bad',
'url': 'https://errors.pydantic.dev/2/v/int_parsing',
},
{
'type': 'float_parsing',
'loc': ('a_float',),
'msg': 'Input should be a valid number, unable to parse string as a number',
'input': 'not a float',
'url': 'https://errors.pydantic.dev/2/v/float_parsing',
},
{
'type': 'float_parsing',
'loc': ('recursive_model', 'lng'),
'msg': 'Input should be a valid number, unable to parse string as a number',
'input': 'New York',
'url': 'https://errors.pydantic.dev/2/v/float_parsing',
},
]
"""
カスタムエラー¶
カスタム データ型またはバリデーターでは、エラーを発生させるためにValueError
またはAssertionError
使用する必要があります。
@validator
デコレータの使用の詳細については、バリデータを参照してください。
from pydantic import BaseModel, ValidationError, field_validator
class Model(BaseModel):
foo: str
@field_validator('foo')
def value_must_equal_bar(cls, v):
if v != 'bar':
raise ValueError('value must be "bar"')
return v
try:
Model(foo='ber')
except ValidationError as e:
print(e)
"""
1 validation error for Model
foo
Value error, value must be "bar" [type=value_error, input_value='ber', input_type=str]
"""
print(e.errors())
"""
[
{
'type': 'value_error',
'loc': ('foo',),
'msg': 'Value error, value must be "bar"',
'input': 'ber',
'ctx': {'error': ValueError('value must be "bar"')},
'url': 'https://errors.pydantic.dev/2/v/value_error',
}
]
"""
PydanticCustomError
を使用して、エラー構造を完全に制御することもできます。
from pydantic_core import PydanticCustomError
from pydantic import BaseModel, ValidationError, field_validator
class Model(BaseModel):
foo: str
@field_validator('foo')
def value_must_equal_bar(cls, v):
if v != 'bar':
raise PydanticCustomError(
'not_a_bar',
'value is not "bar", got "{wrong_value}"',
dict(wrong_value=v),
)
return v
try:
Model(foo='ber')
except ValidationError as e:
print(e)
"""
1 validation error for Model
foo
value is not "bar", got "ber" [type=not_a_bar, input_value='ber', input_type=str]
"""
エラーメッセージ¶
Pydantic は、検証エラーと使用エラーに対して役立つデフォルトのエラー メッセージを提供しようとします。
次のセクションでは、デフォルトのエラー コードに関するドキュメントを提供しています。
エラーメッセージをカスタマイズする¶
カスタム エラー ハンドラーを作成することで、エラー メッセージをカスタマイズできます。
from typing import Dict, List
from pydantic_core import ErrorDetails
from pydantic import BaseModel, HttpUrl, ValidationError
CUSTOM_MESSAGES = {
'int_parsing': 'This is not an integer! 🤦',
'url_scheme': 'Hey, use the right URL scheme! I wanted {expected_schemes}.',
}
def convert_errors(
e: ValidationError, custom_messages: Dict[str, str]
) -> List[ErrorDetails]:
new_errors: List[ErrorDetails] = []
for error in e.errors():
custom_message = custom_messages.get(error['type'])
if custom_message:
ctx = error.get('ctx')
error['msg'] = (
custom_message.format(**ctx) if ctx else custom_message
)
new_errors.append(error)
return new_errors
class Model(BaseModel):
a: int
b: HttpUrl
try:
Model(a='wrong', b='ftp://example.com')
except ValidationError as e:
errors = convert_errors(e, CUSTOM_MESSAGES)
print(errors)
"""
[
{
'type': 'int_parsing',
'loc': ('a',),
'msg': 'This is not an integer! 🤦',
'input': 'wrong',
'url': 'https://errors.pydantic.dev/2/v/int_parsing',
},
{
'type': 'url_scheme',
'loc': ('b',),
'msg': "Hey, use the right URL scheme! I wanted 'http' or 'https'.",
'input': 'ftp://example.com',
'ctx': {'expected_schemes': "'http' or 'https'"},
'url': 'https://errors.pydantic.dev/2/v/url_scheme',
},
]
"""
一般的な使用例は、エラー メッセージの翻訳です。たとえば、上記の例では、 CUSTOM_MESSAGES
辞書を翻訳辞書に置き換えてエラー メッセージを翻訳できます。
別の例は、エラーの'loc'
値を表す方法をカスタマイズすることです。
from typing import Any, Dict, List, Tuple, Union
from pydantic import BaseModel, ValidationError
def loc_to_dot_sep(loc: Tuple[Union[str, int], ...]) -> str:
path = ''
for i, x in enumerate(loc):
if isinstance(x, str):
if i > 0:
path += '.'
path += x
elif isinstance(x, int):
path += f'[{x}]'
else:
raise TypeError('Unexpected type')
return path
def convert_errors(e: ValidationError) -> List[Dict[str, Any]]:
new_errors: List[Dict[str, Any]] = e.errors()
for error in new_errors:
error['loc'] = loc_to_dot_sep(error['loc'])
return new_errors
class TestNestedModel(BaseModel):
key: str
value: str
class TestModel(BaseModel):
items: List[TestNestedModel]
data = {'items': [{'key': 'foo', 'value': 'bar'}, {'key': 'baz'}]}
try:
TestModel.model_validate(data)
except ValidationError as e:
print(e.errors()) # (1)!
"""
[
{
'type': 'missing',
'loc': ('items', 1, 'value'),
'msg': 'Field required',
'input': {'key': 'baz'},
'url': 'https://errors.pydantic.dev/2/v/missing',
}
]
"""
pretty_errors = convert_errors(e)
print(pretty_errors) # (2)!
"""
[
{
'type': 'missing',
'loc': 'items[1].value',
'msg': 'Field required',
'input': {'key': 'baz'},
'url': 'https://errors.pydantic.dev/2/v/missing',
}
]
"""
- デフォルトでは、
e.errors()
タプルの形式をとるloc
値を含むエラーのリストを生成します。 - カスタム
loc_to_dot_sep
関数を使用して、loc
表現の形式を変更しました。
本文总阅读量次