Penanganan Kesalahan
Pydantic akan memunculkan ValidationError
setiap kali menemukan kesalahan pada data yang divalidasinya.
!!! catatan Kode validasi tidak boleh memunculkan ValidationError
itu sendiri, melainkan memunculkan ValueError
atau AssertionError
(atau subkelasnya) yang akan ditangkap dan digunakan untuk mengisi ValidationError
.
Satu pengecualian akan dimunculkan berapapun jumlah kesalahan yang ditemukan, yaitu ValidationError
akan berisi informasi tentang semua kesalahan dan bagaimana kesalahan tersebut terjadi.
Anda dapat mengakses kesalahan ini dalam beberapa cara:
Metode | Keterangan |
---|---|
e.errors() | Mengembalikan daftar kesalahan yang ditemukan pada data input. |
e.error_count() | Mengembalikan jumlah kesalahan yang ditemukan dalam errors . |
e.json() | Mengembalikan representasi errors JSON. |
str(e) | Mengembalikan representasi kesalahan yang dapat dibaca manusia. |
Setiap objek kesalahan berisi:
Milik | Keterangan |
---|---|
ctx | Objek opsional yang berisi nilai yang diperlukan untuk merender pesan kesalahan. |
input | Masukan diberikan untuk validasi. |
loc | Lokasi kesalahan sebagai daftar. |
msg | Penjelasan kesalahan yang dapat dibaca manusia. |
type | Pengidentifikasi jenis kesalahan yang dapat dibaca komputer. |
url | URL untuk informasi lebih lanjut tentang kesalahan tersebut. |
Item pertama dalam daftar loc
akan menjadi bidang di mana kesalahan terjadi, dan jika bidang tersebut adalah sub-model , item berikutnya akan ditampilkan untuk menunjukkan lokasi kesalahan yang bertumpuk.
Sebagai demonstrasi:
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',
},
]
"""
Kesalahan Khusus¶
Dalam tipe data atau validator khusus, Anda harus menggunakan ValueError
atau AssertionError
untuk memunculkan kesalahan.
Lihat validator untuk detail selengkapnya tentang penggunaan dekorator @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',
}
]
"""
Anda juga dapat menggunakan PydanticCustomError
, untuk sepenuhnya mengontrol struktur kesalahan:
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]
"""
Pesan kesalahan¶
Pydantic mencoba memberikan pesan kesalahan default yang berguna untuk kesalahan validasi dan penggunaan.
Kami telah menyediakan dokumentasi untuk kode kesalahan default di bagian berikut:
Sesuaikan pesan kesalahan¶
Anda dapat menyesuaikan pesan kesalahan dengan membuat penangan kesalahan khusus.
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',
},
]
"""
Kasus penggunaan yang umum adalah menerjemahkan pesan kesalahan. Misalnya, dalam contoh di atas, kita dapat menerjemahkan pesan kesalahan dengan mengganti kamus CUSTOM_MESSAGES
dengan kamus terjemahan.
Contoh lainnya adalah menyesuaikan cara representasi nilai 'loc'
dari suatu kesalahan.
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',
}
]
"""
- Secara default,
e.errors()
menghasilkan Daftar kesalahan dengan nilailoc
yang berbentuk tupel. - Dengan fungsi
loc_to_dot_sep
khusus kami, kami telah memodifikasi bentuk representasiloc
.
本文总阅读量次