विषय पर बढ़ें

त्रुटि प्रबंधन

जब भी पाइडेंटिक को अपने द्वारा सत्यापित किए जा रहे डेटा में कोई त्रुटि मिलेगी तो वह ValidationError बढ़ा देगा।

!!! ध्यान दें सत्यापन कोड को ValidationError स्वयं नहीं बढ़ाना चाहिए, बल्कि एक ValueError या AssertionError (या उसके उपवर्ग) को बढ़ाना चाहिए जिसे पकड़ा जाएगा और ValidationError पॉप्युलेट करने के लिए उपयोग किया जाएगा।

पाई गई त्रुटियों की संख्या की परवाह किए बिना एक अपवाद उठाया जाएगा, कि 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]
    """

त्रुटि संदेश

पाइडेंटिक सत्यापन और उपयोग त्रुटियों के लिए उपयोगी डिफ़ॉल्ट त्रुटि संदेश प्रदान करने का प्रयास करता है।

हमने निम्नलिखित अनुभागों में डिफ़ॉल्ट त्रुटि कोड के लिए दस्तावेज़ उपलब्ध कराए हैं:

त्रुटि संदेशों को अनुकूलित करें

आप कस्टम त्रुटि हैंडलर बनाकर त्रुटि संदेशों को अनुकूलित कर सकते हैं।

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',
        }
    ]
    """
  1. डिफ़ॉल्ट रूप से, e.errors() loc मानों के साथ त्रुटियों की एक सूची तैयार करता है जो टुपल्स का रूप लेती है।
  2. हमारे कस्टम loc_to_dot_sep फ़ंक्शन के साथ, हमने loc प्रतिनिधित्व के रूप को संशोधित किया है।

本文总阅读量