Lewati ke isi

Mengapa menggunakan Pydantic?

Saat ini, Pydantic diunduh berkali-kali dalam sebulan dan digunakan oleh beberapa organisasi terbesar dan paling dikenal di dunia.

Sulit untuk mengetahui mengapa begitu banyak orang mengadopsi Pydantic sejak didirikan enam tahun lalu, namun berikut beberapa tebakannya.

Ketik petunjuk yang mendukung validasi skema

Skema yang divalidasi oleh Pydantic umumnya ditentukan oleh petunjuk tipe Python.

Petunjuk mengetik sangat bagus untuk ini karena, jika Anda menulis Python modern, Anda sudah tahu cara menggunakannya. Menggunakan petunjuk tipe juga berarti Pydantic terintegrasi dengan baik dengan alat pengetikan statis seperti mypy dan pyright serta IDE seperti pycharm dan vscode.

???+ contoh "Contoh - cukup ketik petunjuk" (Contoh ini memerlukan Python 3.9+) ```py membutuhkan = "3.9" dari mengetik import Annotated, Dict, List, Literal, Tuple

from annotated_types import Gt

from pydantic import BaseModel


class Fruit(BaseModel):
    name: str  # (1)!
    color: Literal['red', 'green']  # (2)!
    weight: Annotated[float, Gt(0)]  # (3)!
    bazam: Dict[str, List[Tuple[int, bool, float]]]  # (4)!


print(
    Fruit(
        name='Apple',
        color='red',
        weight=4.2,
        bazam={'foobar': [(1, True, 0.1)]},
    )
)
#> name='Apple' color='red' weight=4.2 bazam={'foobar': [(1, True, 0.1)]}
```

1. The `name` field is simply annotated with `str` - any string is allowed.
2. The [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal) type is used to enforce that `color` is either `'red'` or `'green'`.
3. Even when we want to apply constraints not encapsulated in python types, we can use [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) and [`annotated-types`](https://github.com/annotated-types/annotated-types) to enforce constraints without breaking type hints.
4. I'm not claiming "bazam" is really an attribute of fruit, but rather to show that arbitrarily complex types can easily be validated.

!!! tip "Pelajari lebih lanjut" Lihat dokumentasi tentang tipe yang didukung.

Pertunjukan

Logika validasi inti Pydantic diimplementasikan dalam paket terpisah pydantic-core, di mana validasi untuk sebagian besar tipe diimplementasikan di Rust.

Hasilnya, Pydantic adalah salah satu perpustakaan validasi data tercepat untuk Python.

??? contoh "Contoh Kinerja - Pydantic vs. kode khusus" Secara umum, kode khusus seharusnya jauh lebih cepat daripada validator tujuan umum, namun dalam contoh ini Pydantic >300% lebih cepat daripada kode khusus saat mengurai JSON dan memvalidasi URL.

```py title="Performance Example"
import json
import timeit
from urllib.parse import urlparse

import requests

from pydantic import HttpUrl, TypeAdapter

reps = 7
number = 100
r = requests.get('https://api.github.com/emojis')
r.raise_for_status()
emojis_json = r.content


def emojis_pure_python(raw_data):
    data = json.loads(raw_data)
    output = {}
    for key, value in data.items():
        assert isinstance(key, str)
        url = urlparse(value)
        assert url.scheme in ('https', 'http')
        output[key] = url


emojis_pure_python_times = timeit.repeat(
    'emojis_pure_python(emojis_json)',
    globals={
        'emojis_pure_python': emojis_pure_python,
        'emojis_json': emojis_json,
    },
    repeat=reps,
    number=number,
)
print(f'pure python: {min(emojis_pure_python_times) / number * 1000:0.2f}ms')
#> pure python: 5.32ms

type_adapter = TypeAdapter(dict[str, HttpUrl])
emojis_pydantic_times = timeit.repeat(
    'type_adapter.validate_json(emojis_json)',
    globals={
        'type_adapter': type_adapter,
        'HttpUrl': HttpUrl,
        'emojis_json': emojis_json,
    },
    repeat=reps,
    number=number,
)
print(f'pydantic: {min(emojis_pydantic_times) / number * 1000:0.2f}ms')
#> pydantic: 1.54ms

print(
    f'Pydantic {min(emojis_pure_python_times) / min(emojis_pydantic_times):0.2f}x faster'
)
#> Pydantic 3.45x faster
```

Tidak seperti perpustakaan yang berpusat pada kinerja lainnya yang ditulis dalam bahasa yang dikompilasi, Pydantic juga memiliki dukungan yang sangat baik untuk menyesuaikan validasi melalui validator fungsional.

!!! tip "Pelajari lebih lanjut" Pembicaraan Samuel Colvin di PyCon 2023 menjelaskan cara kerja pydantic-core dan cara integrasinya dengan Pydantic.

Serialisasi

Pydantic menyediakan fungsionalitas untuk membuat serial model dalam tiga cara:

  1. Ke dict Python yang terdiri dari objek Python terkait
  2. Untuk dict Python hanya terdiri dari tipe "jsonable".
  3. Ke string JSON

Dalam ketiga mode tersebut, output dapat disesuaikan dengan mengecualikan bidang tertentu, mengecualikan bidang yang tidak disetel, mengecualikan nilai default, dan mengecualikan nilai Tidak Ada.

??? contoh "Contoh - Serialisasi 3 cara" ```py dari datetime import datetime

from pydantic import BaseModel


class Meeting(BaseModel):
    when: datetime
    where: bytes
    why: str = 'No idea'


m = Meeting(when='2020-01-01T12:00', where='home')
print(m.model_dump(exclude_unset=True))
#> {'when': datetime.datetime(2020, 1, 1, 12, 0), 'where': b'home'}
print(m.model_dump(exclude={'where'}, mode='json'))
#> {'when': '2020-01-01T12:00:00', 'why': 'No idea'}
print(m.model_dump_json(exclude_defaults=True))
#> {"when":"2020-01-01T12:00:00","where":"home"}
```

!!! tip "Pelajari lebih lanjut" Lihat dokumentasi tentang serialisasi.

Skema JSON

Skema JSON dapat dibuat untuk skema Pydantic apa pun — memungkinkan API yang terdokumentasi sendiri dan integrasi dengan berbagai alat yang mendukung Skema JSON.

??? contoh "Contoh - Skema JSON" ```py dari datetime import datetime

from pydantic import BaseModel Alamat kelas (Model Dasar): jalan: st kota: str kode pos: str pertemuan kelas (Model Dasar): kapan: tanggal waktu dimana: Alamat mengapa: str = 'Tidak tahu' cetak(Rapat.model_json_schema()) """ { ' $defs': { 'Alamat': { 'properti': { 'jalan': {'judul': 'Jalan', 'tipe': 'string'}, 'kota': {'judul': 'Kota', 'tipe': 'string'}, 'kode pos': {'judul': 'Kode Pos', 'ketik': 'string'}, }, 'wajib': ['jalan', 'kota', 'kode pos'], 'judul': 'Alamat', 'tipe': 'objek', } }, 'properti': { 'kapan': {'format': 'tanggal-waktu', 'judul': 'Kapan', 'ketik': 'string'}, 'di mana': {'$ref': '#/$defs/Alamat'}, 'mengapa': {'default': 'Tidak tahu', 'judul': 'Mengapa', 'ketik': 'string'}, }, 'wajib': ['kapan', 'di mana'], 'judul': 'Pertemuan', 'tipe': 'objek', } """ ```

Pydantic menghasilkan Skema JSON versi 2020-12, versi standar terbaru yang kompatibel dengan OpenAPI 3.1.

!!! tip "Pelajari lebih lanjut" Lihat dokumentasi tentang Skema JSON.

Mode ketat dan pemaksaan data

Secara default, Pydantic toleran terhadap tipe umum yang salah dan memaksa data ke tipe yang benar — misalnya string numerik yang diteruskan ke bidang int akan diurai sebagai int.

Pydantic juga memiliki mode strict=True — juga dikenal sebagai "Mode Ketat" — di mana tipe tidak dipaksakan dan kesalahan validasi muncul kecuali data input sama persis dengan skema atau petunjuk tipe.

Namun mode ketat akan sangat tidak berguna saat memvalidasi data JSON karena JSON tidak memiliki tipe yang cocok dengan banyak tipe python umum seperti datetime, UUID, atau byte.

Untuk mengatasi ini, Pydantic dapat mengurai dan memvalidasi JSON dalam satu langkah. Hal ini memungkinkan konversi data yang masuk akal seperti string RFC3339 (alias ISO8601) ke objek datetime. Karena penguraian JSON diimplementasikan di Rust, kinerjanya juga sangat baik.

??? contoh "Contoh - Mode ketat yang sebenarnya berguna" ```py dari datetime import datetime

from pydantic import BaseModel, ValidationError


class Meeting(BaseModel):
    when: datetime
    where: bytes


m = Meeting.model_validate({'when': '2020-01-01T12:00', 'where': 'home'})
print(m)
#> when=datetime.datetime(2020, 1, 1, 12, 0) where=b'home'
try:
    m = Meeting.model_validate(
        {'when': '2020-01-01T12:00', 'where': 'home'}, strict=True
    )
except ValidationError as e:
    print(e)
    """
    2 validation errors for Meeting
    when
      Input should be a valid datetime [type=datetime_type, input_value='2020-01-01T12:00', input_type=str]
    where
      Input should be a valid bytes [type=bytes_type, input_value='home', input_type=str]
    """

m_json = Meeting.model_validate_json(
    '{"when": "2020-01-01T12:00", "where": "home"}'
)
print(m_json)
#> when=datetime.datetime(2020, 1, 1, 12, 0) where=b'home'
```

!!! tip "Pelajari lebih lanjut" Lihat dokumentasi tentang mode ketat.

Kelas data, TypedDicts, dan lainnya

Pydantic menyediakan empat cara untuk membuat skema dan melakukan validasi dan serialisasi:

  1. BaseModel - Kelas super Pydantic dengan banyak utilitas umum tersedia melalui metode instan.
  2. pydantic.dataclasses.dataclass — pembungkus kelas data standar yang melakukan validasi ketika kelas data diinisialisasi.
  3. TypeAdapter — cara umum untuk mengadaptasi tipe apa pun untuk validasi dan serialisasi. Hal ini memungkinkan tipe seperti TypedDict dan NamedTuple divalidasi serta nilai skalar sederhana seperti int atau timedelta — semua tipe yang didukung dapat digunakan dengan TypeAdapter.
  4. validasi_call — dekorator untuk melakukan validasi saat memanggil suatu fungsi.

??? contoh "Contoh - skema berdasarkan TypedDict" ```py dari datetime import datetime

from typing_extensions import NotRequired, TypedDict

from pydantic import TypeAdapter


class Meeting(TypedDict):
    when: datetime
    where: bytes
    why: NotRequired[str]


meeting_adapter = TypeAdapter(Meeting)
m = meeting_adapter.validate_python(  # (1)!
    {'when': '2020-01-01T12:00', 'where': 'home'}
)
print(m)
#> {'when': datetime.datetime(2020, 1, 1, 12, 0), 'where': b'home'}
meeting_adapter.dump_python(m, exclude={'where'})  # (2)!

print(meeting_adapter.json_schema())  # (3)!
"""
{
    'properties': {
        'when': {'format': 'date-time', 'title': 'When', 'type': 'string'},
        'where': {'format': 'binary', 'title': 'Where', 'type': 'string'},
        'why': {'title': 'Why', 'type': 'string'},
    },
    'required': ['when', 'where'],
    'title': 'Meeting',
    'type': 'object',
}
"""
```

1. `TypeAdapter` for a `TypedDict` performing validation, it can also validate JSON data directly with `validate_json`
2. `dump_python` to serialise a `TypedDict` to a python object, it can also serialise to JSON with `dump_json`
3. `TypeAdapter` can also generate JSON Schema

Kustomisasi

Validator dan serializer fungsional, serta protokol yang kuat untuk tipe khusus, berarti cara pengoperasian Pydantic dapat disesuaikan berdasarkan per bidang atau per jenis.

??? contoh "Contoh Kustomisasi - validator bungkus" "validator bungkus" adalah hal baru di Pydantic V2 dan merupakan salah satu cara paling ampuh untuk menyesuaikan validasi Pydantic. ```py dari datetime impor datetime, zona waktu

from pydantic import BaseModel, field_validator


class Meeting(BaseModel):
    when: datetime

    @field_validator('when', mode='wrap')
    def when_now(cls, input_value, handler):
        if input_value == 'now':
            return datetime.now()
        when = handler(input_value)
        # in this specific application we know tz naive datetimes are in UTC
        if when.tzinfo is None:
            when = when.replace(tzinfo=timezone.utc)
        return when


print(Meeting(when='2020-01-01T12:00+01:00'))
#> when=datetime.datetime(2020, 1, 1, 12, 0, tzinfo=TzInfo(+01:00))
print(Meeting(when='now'))
#> when=datetime.datetime(2032, 1, 2, 3, 4, 5, 6)
print(Meeting(when='2020-01-01T12:00'))
#> when=datetime.datetime(2020, 1, 1, 12, 0, tzinfo=datetime.timezone.utc)
```

!!! tip "Pelajari lebih lanjut" Lihat dokumentasi tentang validator, serializer khusus, dan tipe khusus.

Ekosistem

Pada saat penulisan, terdapat 214.100 repositori di GitHub dan 8.119 paket di PyPI yang bergantung pada Pydantic.

Beberapa perpustakaan terkenal yang bergantung pada Pydantic:

Perpustakaan lainnya yang menggunakan Pydantic dapat ditemukan di Kludex/awesome-pydantic.

Organisasi yang menggunakan Pydantic

Beberapa perusahaan dan organisasi terkemuka menggunakan Pydantic bersama dengan komentar tentang mengapa/bagaimana kami mengetahui mereka menggunakan Pydantic.

Organisasi-organisasi di bawah ini disertakan karena mereka memenuhi satu atau lebih kriteria berikut:

  • Menggunakan pydantic sebagai ketergantungan dalam repositori publik
  • Merujuk lalu lintas ke situs dokumentasi pydantic dari domain internal organisasi - perujuk khusus tidak disertakan karena umumnya tidak berada dalam domain publik
  • Komunikasi langsung antara tim Pydantic dan insinyur yang dipekerjakan oleh organisasi tentang penggunaan Pydantic dalam organisasi

Kami telah menyertakan beberapa detail tambahan jika diperlukan dan sudah ada dalam domain publik.

{{ organisations }}


本文总阅读量