728x90

FastAPI를 공부하면서 pydantic 라이브러리에 대해 알게 되었고, pydantic document를 보게 되면서 공부를 하게되어서 공부하고 깨달은 점에 대해 소개하고자 작성하게 되었습니다.

 

Pydnatic overview


Pydantic은 Python의 타입 힌트를 활용하여 데이터 유효성 검사와 설정 관리를 자동화하는 강력한 라이브러리입니다. 개발자가 데이터 모델을 정의할 때 명확한 데이터 타입을 지정함으로써, Pydantic은 이 모델을 기반으로 데이터의 유효성을 자동으로 검증합니다. 이 과정에서 데이터 타입의 불일치나 필드의 누락과 같은 문제를 즉각적으로 식별하고 처리할 수 있습니다  

다시말하면, 명시해준 데이터 타입과 입력에 대해 data validation을 진행합니다. 이 때, 타입이 다르게 되면 오류를 발생시킵니다. 이와 관련되어 pydantic이 안정되고 특화되어 있고 특히 빨라서 사용합니다.

 

Pydantic Install 


파이썬 3.8 버전 이상에서 사용할 수 있습니다. 

pip install pydantic

 

Pydantic Example


예시를 통해 pydnatic에 대해 알아봅시다

Example 1

from datetime import datetime
from pydantic import BaseModel, PositiveInt


class User(BaseModel):
    id: int  # id는 int값을 가져야 함
    signup_ts: datetime | None  # signup_ts는 datetime 또는 None을 가져야 함
    tastes: dict[str, PositiveInt]  # key는 str, value는 PositiveInt를 가져야 함

external_data = {
    'id': 123,
    'signup_ts': '2019-06-01 12:22',  
    'tastes': {
        'wine': 9,
        'cabbage': '1',
    },
}

user = User(**external_data)

print(user)
# id=123 signup_ts=datetime.datetime(2019, 6, 1, 12, 22) tastes={'wine': 9, 'cabbage': 1}

다음과 같이 지정해준 type과 맞는  자료가 들어오면 정상적으로 출력된다.

 

Example 2

from datetime import datetime
from pydantic import BaseModel, ValidationError, PositiveInt 

class User(BaseModel):
    id: int
    name: str = 'John Doe'
    signup_ts: datetime | None
    tastes: dict[str, PositiveInt]

external_data = {'id': 'not an int', 'tastes': {}}  

try:
    User(**external_data)  
except ValidationError as e:
    print(e.errors())
    """
    [
        {
            'type': 'int_parsing',
            'loc': ('id',),
            'msg': 'Input should be a valid integer, unable to parse string as an integer',
            'input': 'not an int',
            'url': 'https://errors.pydantic.dev/2/v/int_parsing',
        },
        {
            'type': 'missing',
            'loc': ('signup_ts',),
            'msg': 'Field required',
            'input': {'id': 'not an int', 'tastes': {}},
            'url': 'https://errors.pydantic.dev/2/v/missing',
        },
    ]
    """

다음은 지정해준 type을 주지 않을때 오류를 발생시킨다. id에서 int형이 아닌 str형을 입력하려고 해서 ValidationError가 발생한다.

  • type : 오류의 유형을 나타냅니다. int_parsing은 정수 파싱 오류를, missing은 필수 필드가 누락됨을 의미합니다.
  • loc : 오류가 발생한 모델의 위치를 튜플로 나타냅니다. ('id',)id 필드에서 오류가 발생했음을 의미합니다.
  • msg : 오류의 세부적인 설명을 제공합니다. 예를 들어, Input should be a valid integer, unable to parse string as an integer는 입력이 유효한 정수여야 하며, 문자열을 정수로 파싱할 수 없다는 것을 알려줍니다.
  • input : 오류가 발생한 때 받은 입력 데이터를 나타냅니다. 'not an int'id 필드에 부적절한 입력이 제공되었음을 보여줍니다.
  • url : 해당 오류 유형에 대한 더 자세한 정보를 제공하는 웹 페이지의 URL입니다.

 

Validtor Example


field_validator을 이용해서 직접 validtor을 만들 수 있습니다. 다음은 그에 대한 예시입니다.

 

Field Example

from pydantic import (
    BaseModel,
    ValidationError,
    ValidationInfo,
    field_validator,
)

class UserModel(BaseModel):
    name: str
    id: int

    @field_validator('name')
    @classmethod
    def name_must_contain_space(cls, v: str) -> str:
        if ' ' not in v:
            raise ValueError('must contain a space')
        return v.title()

    # 다양한 필드들을 추가할 수 있으며, '*' 기호를 사용하면 모든 필드를 추가할 수 있습니다.
    @field_validator('id', 'name')
    @classmethod
    def check_alphanumeric(cls, v: str, info: ValidationInfo) -> str:
        if isinstance(v, str):
            # info.field_name is the name of the field being validated
            is_alphanumeric = v.replace(' ', '').isalnum()
            assert is_alphanumeric, f'{info.field_name} must be alphanumeric'
        return v
    
try:
    UserModel(username='scolvin', password1='zxcvbn', password2='zxcvbn2')
except ValidationError as e:
    print(e)
    """
    1 validation error for UserModel
      Value error, passwords do not match [type=value_error, input_value={'username': 'scolvin', '... 'password2': 'zxcvbn2'}, input_type=dict]
    """
  • @field_validators는 "클래스 메소드"이므로, 받는 첫 번째 인자는 UserModel 인스턴스가 아닌 UserModel 클래스입니다. 정확한 타입 검사를 위해 @field_validator 데코레이터 아래에 @classmethod 데코레이터를 사용하는 것을 추천합니다.
  • 두 번째 인자는 검증할 필드 값이며, 원하는 대로 이름을 지정할 수 있습니다.
  • 세 번째 인자는 존재한다면 pydantic.ValidationInfo의 인스턴스입니다.

위와 같은 방식으로 만들 수 있습니다.

 

 

출처 : https://docs.pydantic.dev/latest/

728x90