콘텐츠로 이동

성능 팁

대부분의 경우 Pydantic은 병목 현상이 되지 않습니다. 꼭 필요하다고 확신하는 경우에만 이 방법을 따르십시오.

일반적으로 model_validate_json() 사용하지 마세요. model_validate(json.loads(...))

~에 model_validate(json.loads(...)) , JSON은 Python에서 구문 분석된 다음 dict로 변환된 다음 내부적으로 검증됩니다. 반면에 model_validate_json() 이미 내부적으로 유효성 검사를 수행합니다.

몇 가지 경우가 있습니다. model_validate(json.loads(...)) 더 빠를 수도 있습니다. 특히 모델에 'before' 또는 'wrap' 유효성 검사기를 사용하는 경우 2단계 방법을 사용하면 유효성 검사가 더 빨라질 수 있습니다. 이 토론 에서 이러한 특수 사례에 대한 자세한 내용을 읽을 수 있습니다.

여기에 설명된 대로 현재 pydantic-core 에 대한 많은 성능 개선 작업이 진행 중입니다. 이러한 변경 사항이 병합되면 model_validate_json() 이 항상 더 빠른 지점에 도달해야 합니다. model_validate(json.loads(...)) .

TypeAdapter 한 번 인스턴스화됨

여기서의 아이디어는 필요 이상으로 유효성 검사기와 직렬 변환기를 구성하지 않는 것입니다. TypeAdapter 가 인스턴스화될 때마다 새로운 유효성 검사기와 직렬 변환기가 구성됩니다. 함수에서 TypeAdapter 를 사용하는 경우 함수가 호출될 때마다 인스턴스화됩니다. 대신, 한 번 인스턴스화하고 재사용하세요.

\=== "❌ 나쁨"

```py
from typing import List

from pydantic import TypeAdapter


def my_func():
    adapter = TypeAdapter(List[int])
    # do something with adapter
```

\=== "✅ 좋음"

```py
from typing import List

from pydantic import TypeAdapter

adapter = TypeAdapter(List[int])

def my_func():
    ...
    # do something with adapter
```

Sequencelist 또는 tuple - Mappingdict

Sequence 사용할 때 Pydantic은 isinstance(value, Sequence) 호출하여 값이 시퀀스인지 확인합니다. 또한 Pydantic은 listtuple 과 같은 다양한 유형의 시퀀스에 대해 유효성을 검사하려고 시도합니다. 값이 list 또는 tuple 이라는 것을 알고 있다면 Sequence 대신 list 또는 tuple 사용하세요.

Mappingdict 에도 동일하게 적용됩니다. 값이 dict 임을 알고 있다면 Mapping 대신 dict 사용하세요.

필요하지 않은 경우 유효성 검사를 수행하지 마세요. 값을 변경하지 않고 유지하려면 Any 사용하세요.

값의 유효성을 검사할 필요가 없으면 Any 사용하여 값을 변경하지 않고 유지하세요.

from typing import Any

from pydantic import BaseModel


class Model(BaseModel):
    a: Any


model = Model(a=1)

프리미티브의 서브클래스를 통해 추가 정보 방지

\=== "이러지 마세요"

```py
class CompletedStr(str):
    def __init__(self, s: str):
        self.s = s
        self.done = False
```

\=== "이렇게 하세요"

```py
from pydantic import BaseModel


class CompletedModel(BaseModel):
    s: str
    done: bool = False
```

Union이 아닌 태그된 Union을 사용하세요.

태그된 공용체(또는 구별된 공용체)는 어떤 유형인지 나타내는 필드가 있는 공용체입니다.

from typing import Any

from typing_extensions import Literal

from pydantic import BaseModel, Field


class DivModel(BaseModel):
    el_type: Literal['div'] = 'div'
    class_name: str | None = None
    children: list[Any] | None = None


class SpanModel(BaseModel):
    el_type: Literal['span'] = 'span'
    class_name: str | None = None
    contents: str | None = None


class ButtonModel(BaseModel):
    el_type: Literal['button'] = 'button'
    class_name: str | None = None
    contents: str | None = None


class InputModel(BaseModel):
    el_type: Literal['input'] = 'input'
    class_name: str | None = None
    value: str | None = None


class Html(BaseModel):
    contents: DivModel | SpanModel | ButtonModel | InputModel = Field(
        discriminator='el_type'
    )

자세한 내용은 차별된 공용체를 참조하세요.

중첩 모델보다 TypedDict 사용

중첩 모델을 사용하는 대신 TypedDict 사용하여 데이터 구조를 정의하세요.

??? info "성능 비교" 간단한 벤치마크를 통해 TypedDict 는 중첩 모델보다 약 2.5배 빠릅니다.

```py
from timeit import timeit

from typing_extensions import TypedDict

from pydantic import BaseModel, TypeAdapter


class A(TypedDict):
    a: str
    b: int


class TypedModel(TypedDict):
    a: A


class B(BaseModel):
    a: str
    b: int


class Model(BaseModel):
    b: B


ta = TypeAdapter(TypedModel)
result1 = timeit(
    lambda: ta.validate_python({'a': {'a': 'a', 'b': 2}}), number=10000
)
result2 = timeit(
    lambda: Model.model_validate({'b': {'a': 'a', 'b': 2}}), number=10000
)
print(result2 / result1)
```

성능에 정말로 관심이 있다면 랩 유효성 검사기를 사용하지 마세요.

랩 유효성 검사기는 일반적으로 다른 유효성 검사기보다 느립니다. 이는 검증 중에 데이터가 Python에서 구체화되어야 하기 때문입니다. 랩 유효성 검사기는 복잡한 유효성 검사 논리에 매우 유용할 수 있지만 최고의 성능을 찾고 있다면 피해야 합니다.

FailFast 로 조기 실패

v2.8+부터 시퀀스 유형에 FailFast 주석을 적용하여 시퀀스의 항목이 유효성 검사에 실패할 경우 조기에 실패하도록 할 수 있습니다. 이 주석을 사용하면 시퀀스의 나머지 항목 중 하나가 실패하더라도 유효성 검사 오류가 발생하지 않으므로 가시성과 성능을 효과적으로 절충할 수 있습니다.

from typing import List

from typing_extensions import Annotated

from pydantic import FailFast, TypeAdapter, ValidationError

ta = TypeAdapter(Annotated[List[bool], FailFast()])
try:
    ta.validate_python([True, 'invalid', False, 'also invalid'])
except ValidationError as exc:
    print(exc)
    """
    1 validation error for list[bool]
    1
      Input should be a valid boolean, unable to interpret input [type=bool_parsing, input_value='invalid', input_type=str]
    """

FailFast 에 대해 여기에서 자세히 알아보세요.


本文总阅读量