The Boxer

pydantic 본문

Python

pydantic

Prower 2022. 7. 7. 02:11
728x90
반응형
  • python에서 사용하는 data parsing and validation 라이브러리
  • parsing과 validation을 담당한다고 적었는데 pydantic이 data를 어떻게 parsing하고 validation 하는지 확인해보자.

작동 순서

정상 파싱이 가능한 경우

from datetime import datetime
from typing import List, Tuple
from pydantic import BaseModel
​
​
class Bar(BaseModel):
    id: int
    name: str
​
​
class Foo(BaseModel):
    id: int
    name: str
    numbers: List[int]
    tup: Tuple[str, int]
    bar: Bar
​
​
template = {
    "id": "1",
    "name": "foo",
    "numbers": [ 1, 2, "3" ],
    "tup": [ 1, "2" ],
    "bar": {
        "id": "2",
        "name": "bar"
    },
    "additional": "testing"
}
​
foo = Foo(**template)
​
print(foo)
​

출력 결과

id=1 name='foo' numbers=[1, 2, 3] tup=('1', 2) bar=Bar(id=2, name='bar')
  • 두 클래스를 선언하고 dictionary 값을 생성자의 인자로 전달하였다
  • 출력값을 확인해보면 각 값이 어떻게 파싱 되었는지 확인할 수 있는데
    • 클래스에서 각 필드에 정의해 놓은 type 대로 파싱 이루어 진 것
    • 클래스에서 정의하지 않은 값은 포함되지 않은 것을 확인할 수 있다.

파싱이 불가능한 경우

template = {
    "id": "testing",
    "name": "foo",
    "numbers": [ 1, 2, "3" ],
    "tup": [ 1, "2" ],
    "bar": {
        "id": "2",
        "name": "bar"
    },
    "additional": "testing"
}
​
try:
    foo = Foo(**template)
except ValidationError as e:
    print(e.json())
​

출력 결과

[
  {
    "loc": [
      "id"
    ],
    "msg": "value is not a valid integer",
    "type": "type_error.integer"
  }
]
  • id 값을 int형으로 변환할 수 없는 값을 전달하면 error을 던지며 관련된 메세지를 출력한다.
  • 여기서 확인할 수 있는 것은
    • pydantic은 1차적으로 데이터 파싱을 진행한다.
    • 파싱이 불가능한 경우 validation 처리를 하며 error를 던진다.

정리

  • pydantic은 입력 데이터를 파싱하여 개발자가 정의한 type과 제약 조건을 보장한다.

Model

  • pydantic에서 BaseModel 을 상속받아 정의한 객체를 model이라 한다.
  • 위에서 정리한 목적에서 나와있듯이 입력 데이터를 개발자가 정의한 type과 제약 조건을 보장하도록 파싱하는 객체로 이해할 수 있겠다.
  • BaseModel 을 상속받으면 pydantic에서 제공하는 메서드를 같이 상속받는다. 관련 리스트는 링크 에서 확인할 수 있다.

validator

  • pydantic의 주 목적이 파싱이라고 설명했지만, validation에 대한 기능 또한 제공한다.
  • validator 어노테이션을 사용하여 Model에 대해 좀 더 복잡한 제약 조건 설정이 가능하다.
from pydantic import BaseModel, ValidationError, validator
​
class Foo(BaseModel):
    name: str
​
    @validator('name')
    def foo_name(cls, value):
        if 'foo' not in value:
            raise ValueError('must contain foo')
        return value
​
template = {
    "name": "foo_test_name",
}
​
foo = Foo(**template)
print(foo)
​
template2 = {
    "name": "test_name"
}
​
try:
    bar = Foo(**template2)
    print(bar)
except ValidationError as e:
    print(e.json())
​

출력 결과

name='foo_test_name'
[
  {
    "loc": [
      "name"
    ],
    "msg": "must contain foo",
    "type": "value_error"
  }
]

 

728x90
반응형

'Python' 카테고리의 다른 글

python mutable, immutable  (0) 2022.07.23
python object interning  (0) 2022.07.22
python dataclass  (0) 2022.07.21
Python class, instance 변수  (0) 2022.07.19
Fixture, Mock, Spy  (0) 2022.07.01
Comments