विषय पर बढ़ें

सख्त मोड

??? एपीआई "एपीआई दस्तावेज़ीकरण" pydantic.types.Strict

डिफ़ॉल्ट रूप से, पाइडेंटिक जब संभव हो तो वांछित प्रकार के मानों को बाध्य करने का प्रयास करेगा। उदाहरण के लिए, आप स्ट्रिंग "123" एक int फ़ील्ड में इनपुट के रूप में पास कर सकते हैं, और इसे 123 में बदल दिया जाएगा। यह ज़बरदस्ती व्यवहार कई परिदृश्यों में उपयोगी है - सोचें: यूयूआईडी, यूआरएल पैरामीटर, HTTP हेडर, पर्यावरण चर, उपयोगकर्ता इनपुट, आदि।

हालाँकि, ऐसी स्थितियाँ भी हैं जहाँ यह वांछनीय नहीं है, और आप चाहते हैं कि पाइडेंटिक डेटा को ज़बरदस्ती करने के बजाय त्रुटि करे।

इस उपयोग के मामले का बेहतर समर्थन करने के लिए, पाइडेंटिक एक "सख्त मोड" प्रदान करता है जिसे प्रति-मॉडल, प्रति-फ़ील्ड, या यहां तक कि प्रति-सत्यापन-कॉल के आधार पर सक्षम किया जा सकता है। जब सख्त मोड सक्षम किया जाता है, तो डेटा को ज़बरदस्ती करते समय पाइडेंटिक बहुत कम उदार होगा, और यदि डेटा सही प्रकार का नहीं है तो इसके बजाय त्रुटि होगी।

सख्त और डिफ़ॉल्ट/"लैक्स" मोड में सत्यापन व्यवहार के बीच अंतर दिखाने वाला एक संक्षिप्त उदाहरण यहां दिया गया है:

from pydantic import BaseModel, ValidationError


class MyModel(BaseModel):
    x: int


print(MyModel.model_validate({'x': '123'}))  # lax mode
#> x=123

try:
    MyModel.model_validate({'x': '123'}, strict=True)  # strict mode
except ValidationError as exc:
    print(exc)
    """
    1 validation error for MyModel
    x
      Input should be a valid integer [type=int_type, input_value='123', input_type=str]
    """

पाइडेंटिक का उपयोग करते समय सख्त-मोड सत्यापन प्राप्त करने के कई तरीके हैं, जिन पर नीचे अधिक विस्तार से चर्चा की जाएगी:

ज़बरदस्ती को सख्त मोड में टाइप करें

अधिकांश प्रकारों के लिए, सख्त मोड में पायथन से डेटा को मान्य करते समय, केवल सटीक प्रकारों के उदाहरण स्वीकार किए जाते हैं। उदाहरण के लिए, किसी int फ़ील्ड को मान्य करते समय, केवल int के उदाहरण स्वीकार किए जाते हैं; float या str के उदाहरणों को पारित करने के परिणामस्वरूप ValidationError बढ़ जाएगा।

ध्यान दें कि JSON से डेटा को सख्त मोड में सत्यापित करते समय हम ढीले होते हैं। उदाहरण के लिए, UUID फ़ील्ड को सत्यापित करते समय, JSON से सत्यापित करते समय str के उदाहरण स्वीकार किए जाएंगे, लेकिन पायथन से नहीं:

import json
from uuid import UUID

from pydantic import BaseModel, ValidationError


class MyModel(BaseModel):
    guid: UUID


data = {'guid': '12345678-1234-1234-1234-123456789012'}

print(MyModel.model_validate(data))  # OK: lax
#> guid=UUID('12345678-1234-1234-1234-123456789012')

print(
    MyModel.model_validate_json(json.dumps(data), strict=True)
)  # OK: strict, but from json
#> guid=UUID('12345678-1234-1234-1234-123456789012')

try:
    MyModel.model_validate(data, strict=True)  # Not OK: strict, from python
except ValidationError as exc:
    print(exc.errors(include_url=False))
    """
    [
        {
            'type': 'is_instance_of',
            'loc': ('guid',),
            'msg': 'Input should be an instance of UUID',
            'input': '12345678-1234-1234-1234-123456789012',
            'ctx': {'class': 'UUID'},
        }
    ]
    """

सख्त मोड में इनपुट के रूप में किस प्रकार की अनुमति है, इसके बारे में अधिक जानकारी के लिए, आप रूपांतरण तालिका की समीक्षा कर सकते हैं।

विधि कॉल में सख्त मोड

अब तक शामिल किए गए सभी उदाहरण सत्यापन विधियों के लिए कीवर्ड तर्क के रूप में strict=True के उपयोग के माध्यम से सख्त-मोड सत्यापन प्राप्त करते हैं। जबकि हमने इसे BaseModel.model_validate के लिए दिखाया है, यह TypeAdapter के उपयोग के माध्यम से मनमाने प्रकारों के साथ भी काम करता है:

from pydantic import TypeAdapter, ValidationError

print(TypeAdapter(bool).validate_python('yes'))  # OK: lax
#> True

try:
    TypeAdapter(bool).validate_python('yes', strict=True)  # Not OK: strict
except ValidationError as exc:
    print(exc)
    """
    1 validation error for bool
      Input should be a valid boolean [type=bool_type, input_value='yes', input_type=str]
    """

ध्यान दें कि TypeAdapter में अधिक "जटिल" प्रकारों का उपयोग करते समय भी यह काम करता है:

from dataclasses import dataclass

from pydantic import TypeAdapter, ValidationError


@dataclass
class MyDataclass:
    x: int


try:
    TypeAdapter(MyDataclass).validate_python({'x': '123'}, strict=True)
except ValidationError as exc:
    print(exc)
    """
    1 validation error for MyDataclass
      Input should be an instance of MyDataclass [type=dataclass_exact_type, input_value={'x': '123'}, input_type=dict]
    """

यह TypeAdapter.validate_json और BaseModel.model_validate_json विधियों के साथ भी काम करता है:

import json
from typing import List
from uuid import UUID

from pydantic import BaseModel, TypeAdapter, ValidationError

try:
    TypeAdapter(List[int]).validate_json('["1", 2, "3"]', strict=True)
except ValidationError as exc:
    print(exc)
    """
    2 validation errors for list[int]
    0
      Input should be a valid integer [type=int_type, input_value='1', input_type=str]
    2
      Input should be a valid integer [type=int_type, input_value='3', input_type=str]
    """


class Model(BaseModel):
    x: int
    y: UUID


data = {'x': '1', 'y': '12345678-1234-1234-1234-123456789012'}
try:
    Model.model_validate(data, strict=True)
except ValidationError as exc:
    # Neither x nor y are valid in strict mode from python:
    print(exc)
    """
    2 validation errors for Model
    x
      Input should be a valid integer [type=int_type, input_value='1', input_type=str]
    y
      Input should be an instance of UUID [type=is_instance_of, input_value='12345678-1234-1234-1234-123456789012', input_type=str]
    """

json_data = json.dumps(data)
try:
    Model.model_validate_json(json_data, strict=True)
except ValidationError as exc:
    # From JSON, x is still not valid in strict mode, but y is:
    print(exc)
    """
    1 validation error for Model
    x
      Input should be a valid integer [type=int_type, input_value='1', input_type=str]
    """

Field के साथ सख्त मोड

किसी मॉडल पर अलग-अलग फ़ील्ड के लिए, आप फ़ील्ड पर strict=True सेट कर सकते हैं। इससे उस फ़ील्ड के लिए सख्त-मोड सत्यापन का उपयोग किया जाएगा, तब भी जब सत्यापन विधियों को strict=True के बिना बुलाया जाता है।

केवल वे फ़ील्ड जिनके लिए strict=True सेट है, प्रभावित होंगे:

from pydantic import BaseModel, Field, ValidationError


class User(BaseModel):
    name: str
    age: int
    n_pets: int


user = User(name='John', age='42', n_pets='1')
print(user)
#> name='John' age=42 n_pets=1


class AnotherUser(BaseModel):
    name: str
    age: int = Field(strict=True)
    n_pets: int


try:
    anotheruser = AnotherUser(name='John', age='42', n_pets='1')
except ValidationError as e:
    print(e)
    """
    1 validation error for AnotherUser
    age
      Input should be a valid integer [type=int_type, input_value='42', input_type=str]
    """

ध्यान दें कि फ़ील्ड को सख्त बनाने से मॉडल वर्ग को इंस्टेंट करते समय किए गए सत्यापन पर भी असर पड़ेगा:

from pydantic import BaseModel, Field, ValidationError


class Model(BaseModel):
    x: int = Field(strict=True)
    y: int = Field(strict=False)


try:
    Model(x='1', y='2')
except ValidationError as exc:
    print(exc)
    """
    1 validation error for Model
    x
      Input should be a valid integer [type=int_type, input_value='1', input_type=str]
    """

एनोटेशन के रूप में Field उपयोग करना

ध्यान दें कि यदि आवश्यक हो तो Field(strict=True) (या किसी अन्य कीवर्ड तर्क के साथ) को एनोटेशन के रूप में उपयोग किया जा सकता है, उदाहरण के लिए, TypedDict के साथ काम करते समय:

from typing_extensions import Annotated, TypedDict

from pydantic import Field, TypeAdapter, ValidationError


class MyDict(TypedDict):
    x: Annotated[int, Field(strict=True)]


try:
    TypeAdapter(MyDict).validate_python({'x': '1'})
except ValidationError as exc:
    print(exc)
    """
    1 validation error for typed-dict
    x
      Input should be a valid integer [type=int_type, input_value='1', input_type=str]
    """

Annotated[..., Strict()]

??? एपीआई "एपीआई दस्तावेज़ीकरण" pydantic.types.Strict

पाइडेंटिक Strict क्लास भी प्रदान करता है, जिसका उद्देश्य typing.Annotated क्लास के साथ मेटाडेटा के रूप में उपयोग करना है; यह एनोटेशन इंगित करता है कि एनोटेटेड फ़ील्ड को सख्त मोड में मान्य किया जाना चाहिए:

from typing_extensions import Annotated

from pydantic import BaseModel, Strict, ValidationError


class User(BaseModel):
    name: str
    age: int
    is_active: Annotated[bool, Strict()]


User(name='David', age=33, is_active=True)
try:
    User(name='David', age=33, is_active='True')
except ValidationError as exc:
    print(exc)
    """
    1 validation error for User
    is_active
      Input should be a valid boolean [type=bool_type, input_value='True', input_type=str]
    """

यह वास्तव में, पाइडेंटिक द्वारा प्रदान किए गए कुछ सख्त-आउट-ऑफ-द-बॉक्स प्रकारों को लागू करने के लिए उपयोग की जाने वाली विधि है, जैसे कि StrictInt

ConfigDict के साथ सख्त मोड

BaseModel

यदि आप जटिल इनपुट प्रकार पर सभी फ़ील्ड के लिए सख्त मोड सक्षम करना चाहते हैं, तो आप model_config में ConfigDict(strict=True) उपयोग कर सकते हैं:

from pydantic import BaseModel, ConfigDict, ValidationError


class User(BaseModel):
    model_config = ConfigDict(strict=True)

    name: str
    age: int
    is_active: bool


try:
    User(name='David', age='33', is_active='yes')
except ValidationError as exc:
    print(exc)
    """
    2 validation errors for User
    age
      Input should be a valid integer [type=int_type, input_value='33', input_type=str]
    is_active
      Input should be a valid boolean [type=bool_type, input_value='yes', input_type=str]
    """

!!! ध्यान दें किसी मॉडल के model_config के माध्यम से strict=True का उपयोग करते समय, आप अभी भी अलग-अलग फ़ील्ड पर strict=False सेट करके अलग-अलग फ़ील्ड की सख्ती को ओवरराइड कर सकते हैं:

```py
from pydantic import BaseModel, ConfigDict, Field


class User(BaseModel):
    model_config = ConfigDict(strict=True)

    name: str
    age: int = Field(strict=False)
```

ध्यान दें कि सख्त मोड नेस्टेड मॉडल फ़ील्ड पर पुनरावर्ती रूप से लागू नहीं होता है:

from pydantic import BaseModel, ConfigDict, ValidationError


class Inner(BaseModel):
    y: int


class Outer(BaseModel):
    model_config = ConfigDict(strict=True)

    x: int
    inner: Inner


print(Outer(x=1, inner=Inner(y='2')))
#> x=1 inner=Inner(y=2)

try:
    Outer(x='1', inner=Inner(y='2'))
except ValidationError as exc:
    print(exc)
    """
    1 validation error for Outer
    x
      Input should be a valid integer [type=int_type, input_value='1', input_type=str]
    """

(यह डेटाक्लास और TypedDict का भी मामला है।)

यदि यह अवांछनीय है, तो आपको यह सुनिश्चित करना चाहिए कि इसमें शामिल सभी प्रकारों के लिए सख्त मोड सक्षम है। उदाहरण के लिए, यह साझा बेस क्लास का उपयोग करके मॉडल कक्षाओं के लिए किया जा सकता है model_config = ConfigDict(strict=True) :

from pydantic import BaseModel, ConfigDict, ValidationError


class MyBaseModel(BaseModel):
    model_config = ConfigDict(strict=True)


class Inner(MyBaseModel):
    y: int


class Outer(MyBaseModel):
    x: int
    inner: Inner


try:
    Outer.model_validate({'x': 1, 'inner': {'y': '2'}})
except ValidationError as exc:
    print(exc)
    """
    1 validation error for Outer
    inner.y
      Input should be a valid integer [type=int_type, input_value='2', input_type=str]
    """

डेटाक्लास और TypedDict

पाइडेंटिक डेटाक्लास BaseModel के साथ ऊपर दिखाए गए उदाहरणों के समान व्यवहार करते हैं, बस model_config के बजाय आपको config कीवर्ड तर्क का उपयोग करना चाहिए @pydantic.dataclasses.dataclass डेकोरेटर.

जब संभव हो, तो आप pydantic.types.Strict एनोटेशन के साथ फ़ील्ड्स को एनोटेट करके वेनिला डेटाक्लास या TypedDict उपवर्गों के लिए नेस्टेड स्ट्रिक्ट मोड प्राप्त कर सकते हैं।

हालाँकि, यदि यह संभव नहीं है (उदाहरण के लिए, तृतीय-पक्ष प्रकारों के साथ काम करते समय), तो आप प्रकार पर __pydantic_config__ विशेषता सेट करके उस कॉन्फ़िगरेशन को सेट कर सकते हैं जिसे Pydantic को प्रकार के लिए उपयोग करना चाहिए:

from typing_extensions import TypedDict

from pydantic import ConfigDict, TypeAdapter, ValidationError


class Inner(TypedDict):
    y: int


Inner.__pydantic_config__ = ConfigDict(strict=True)


class Outer(TypedDict):
    x: int
    inner: Inner


adapter = TypeAdapter(Outer)
print(adapter.validate_python({'x': '1', 'inner': {'y': 2}}))
#> {'x': 1, 'inner': {'y': 2}}


try:
    adapter.validate_python({'x': '1', 'inner': {'y': '2'}})
except ValidationError as exc:
    print(exc)
    """
    1 validation error for typed-dict
    inner.y
      Input should be a valid integer [type=int_type, input_value='2', input_type=str]
    """

TypeAdapter

आप TypeAdapter क्लास में कॉन्फिग कीवर्ड तर्क के उपयोग के माध्यम से सख्त मोड भी प्राप्त कर सकते हैं:

from pydantic import ConfigDict, TypeAdapter, ValidationError

adapter = TypeAdapter(bool, config=ConfigDict(strict=True))

try:
    adapter.validate_python('yes')
except ValidationError as exc:
    print(exc)
    """
    1 validation error for bool
      Input should be a valid boolean [type=bool_type, input_value='yes', input_type=str]
    """

@validate_call

config कीवर्ड तर्क को पारित करके @validate_call डेकोरेटर के साथ सख्त मोड भी प्रयोग योग्य है:

from pydantic import ConfigDict, ValidationError, validate_call


@validate_call(config=ConfigDict(strict=True))
def foo(x: int) -> int:
    return x


try:
    foo('1')
except ValidationError as exc:
    print(exc)
    """
    1 validation error for foo
    0
      Input should be a valid integer [type=int_type, input_value='1', input_type=str]
    """

本文总阅读量