Zum Inhalt

Leistungstipps

In den meisten Fällen wird Pydantic nicht Ihr Flaschenhals sein. Befolgen Sie dies nur, wenn Sie sicher sind, dass es notwendig ist.

Im Allgemeinen verwenden Sie model_validate_json() nicht model_validate(json.loads(...))

An model_validate(json.loads(...)) , wird der JSON in Python analysiert, dann in ein Diktat konvertiert und dann intern validiert. Andererseits führt model_validate_json() die Validierung bereits intern durch.

Es gibt einige Fälle, in denen model_validate(json.loads(...)) kann schneller sein. Insbesondere wenn ein 'before' oder 'wrap' -Validator für ein Modell verwendet wird, kann die Validierung mit der zweistufigen Methode schneller sein. Mehr über diese Sonderfälle können Sie in dieser Diskussion lesen.

Viele Leistungsverbesserungen sind derzeit für pydantic-core in Arbeit, wie hier besprochen. Sobald diese Änderungen zusammengeführt sind, sollten wir an dem Punkt angelangt sein, an dem model_validate_json() immer schneller ist als model_validate(json.loads(...)) .

TypeAdapter einmal instanziiert

Die Idee dabei ist, die Konstruktion von Validatoren und Serialisierern nicht mehr als nötig zu vermeiden. Jedes Mal, wenn ein TypeAdapter instanziiert wird, erstellt er einen neuen Validator und Serialisierer. Wenn Sie einen TypeAdapter in einer Funktion verwenden, wird dieser bei jedem Aufruf der Funktion instanziiert. Instanziieren Sie es stattdessen einmal und verwenden Sie es erneut.

\=== „❌ Schlecht“

```py
from typing import List

from pydantic import TypeAdapter


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

\=== "✅ Gut"

```py
from typing import List

from pydantic import TypeAdapter

adapter = TypeAdapter(List[int])

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

Sequence vs. list oder tupleMapping vs. dict

Bei Verwendung von Sequence ruft Pydantic isinstance(value, Sequence) auf, um zu überprüfen, ob der Wert eine Sequenz ist. Außerdem wird Pydantic versuchen, eine Validierung anhand verschiedener Arten von Sequenzen durchzuführen, z. B. list und tuple . Wenn Sie wissen, dass der Wert eine list oder tuple ist, verwenden Sie list oder tuple anstelle von Sequence .

Das Gleiche gilt für Mapping und dict . Wenn Sie wissen, dass der Wert ein dict ist, verwenden Sie dict anstelle von Mapping .

Führen Sie keine Validierung durch, wenn dies nicht erforderlich ist. Verwenden Sie Any , um den Wert unverändert zu lassen

Wenn Sie einen Wert nicht validieren müssen, verwenden Sie Any , um den Wert unverändert zu lassen.

from typing import Any

from pydantic import BaseModel


class Model(BaseModel):
    a: Any


model = Model(a=1)

Vermeiden Sie zusätzliche Informationen über Unterklassen von Grundelementen

\=== „Tu das nicht“

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

\=== „Mach das“

```py
from pydantic import BaseModel


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

Verwenden Sie getaggte Union, nicht Union

Eine getaggte Union (oder diskriminierte Union) ist eine Union mit einem Feld, das angibt, um welchen Typ es sich handelt.

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'
    )

Weitere Einzelheiten finden Sie unter „Diskriminierte Gewerkschaften“ .

Verwenden Sie TypedDict für verschachtelte Modelle

Anstatt verschachtelte Modelle zu verwenden, verwenden Sie TypedDict um die Struktur der Daten zu definieren.

??? Info „Leistungsvergleich“ Mit einem einfachen Benchmark ist TypedDict etwa ~2,5x schneller als verschachtelte Modelle:

```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)
```

Vermeiden Sie Wrap-Validatoren, wenn Ihnen die Leistung wirklich am Herzen liegt

Wrap-Validatoren sind im Allgemeinen langsamer als andere Validatoren. Dies liegt daran, dass sie erfordern, dass Daten während der Validierung in Python materialisiert werden. Wrap-Validatoren können für komplexe Validierungslogik unglaublich nützlich sein, aber wenn Sie auf der Suche nach der besten Leistung sind, sollten Sie sie meiden.

Mit FailFast frühzeitig scheitern

Ab Version 2.8+ können Sie die FailFast -Annotation auf Sequenztypen anwenden, um frühzeitig fehlzuschlagen, wenn ein Element in der Sequenz die Validierung nicht besteht. Wenn Sie diese Annotation verwenden, erhalten Sie keine Validierungsfehler für die restlichen Elemente in der Sequenz, wenn eines davon fehlschlägt, Sie tauschen also effektiv Sichtbarkeit gegen Leistung ein.

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]
    """

Lesen Sie mehr über FailFast hier.


本文总阅读量