パフォーマンスのヒント¶
ほとんどの場合、Pydantic がボトルネックになることはありません。確実に必要な場合にのみこれに従ってください。
一般に、 model_validate_json()
を使用します。 model_validate(json.loads(...))
¶
の上 model_validate(json.loads(...))
、JSON は Python で解析され、辞書に変換され、内部で検証されます。一方、 model_validate_json()
すでに内部で検証を実行しています。
いくつかのケースがありますが、 model_validate(json.loads(...))
より速いかもしれません。具体的には、モデルで'before'
バリデーターまたは'wrap'
バリデーターを使用する場合、2 ステップの方法を使用すると検証が高速になる可能性があります。これらの特殊なケースについて詳しくは、この説明を参照してください。
ここで説明されているように、 pydantic-core
では現在、多くのパフォーマンスの改善が行われています。これらの変更がマージされると、 model_validate_json()
の方が常に高速になるはずです。 model_validate(json.loads(...))
。
TypeAdapter
一度インスタンス化される¶
ここでの考え方は、バリデーターとシリアライザーを必要以上に構築しないようにすることです。 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
```
Sequence
とlist
またはtuple
- Mapping
とdict
¶
Sequence
を使用する場合、Pydantic はisinstance(value, Sequence)
を呼び出して、値がシーケンスであるかどうかを確認します。また、Pydantic は、 list
やtuple
などのさまざまなタイプのシーケンスに対して検証を試みます。値がlist
またはtuple
であることがわかっている場合は、 Sequence
代わりにlist
またはtuple
使用します。
同じことがMapping
とdict
にも当てはまります。値が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
アノテーションをシーケンス タイプに適用できます。このアノテーションを使用すると、シーケンス内の項目の 1 つが失敗しても、残りの項目で検証エラーが発生しないため、事実上、可視性とパフォーマンスをトレードオフすることになります。
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
詳細については、こちら をご覧ください。
本文总阅读量次