Why use Pydantic?¶
現在、Pydanticは月に何度もダウンロードされており、世界で最も大きく、最も有名な組織によって使用されています。
Pydanticが6年前に開始されて以来、なぜ多くの人がPydanticを採用しているのかを知るのは難しいですが、いくつか考えられることがあります。
Type hints powering schema validation¶
Pydanticが検証するスキーマは、一般にPythonの型ヒントによって定義されます。
最近のPythonを作成している人であれば、すでに使い方を知っているはずなので、型のヒントはこの目的には最適です。 型ヒントを使用することは、Pydanticがmypyやpyrightのような静的型付けツールやpycharmやvscodeのようなIDEとうまく統合されることも意味します。
Example - just type hints
(This example requires Python 3.9+)
from typing 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)]}
- The
name
field is simply annotated withstr
- any string is allowed. - The
Literal
type is used to enforce thatcolor
is either'red'
or'green'
. - Even when we want to apply constraints not encapsulated in python types, we can use
Annotated
andannotated-types
to enforce constraints without breaking type hints. - I'm not claiming "bazam" is really an attribute of fruit, but rather to show that arbitrarily complex types can easily be validated.
さらなる学習
documentation on supported typesを参照してください。
Performance¶
Pydanticのコア検証ロジックは、別のパッケージpydantic-core
に実装されており、ほとんどのタイプの検証はRustで実装されています。
その結果、PydanticはPython用の最も高速なデータ検証ライブラリの1つになっています。
Performance Example - Pydantic vs. dedicated code
In general, dedicated code should be much faster than a general-purpose validator, but in this example Pydantic is >300% faster than dedicated code when parsing JSON and validating URLs.
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
コンパイル言語で記述された他のパフォーマンス中心のライブラリとは異なり、Pydanticはfunctional validatorsによる検証のカスタマイズにも優れたサポートを提供しています。
さらなる学習
Samuel Colvinのtalk at PyCon 2023は、pydantic-core
がどのように機能し、どのようにPydanticと統合されているか解説しています。
Serialization¶
Pydanticは、次の3つの方法でモデルをシリアライズする機能を提供します。
- Pythonの
dict
に、関連付けられたPythonオブジェクトに構成する - Pythonの
dict
に、"jsonable"な型だけで構成する - JSON文字列への変換
3つのモードすべてにおいて、特定のフィールドを除外し、未設定のフィールドを除外し、デフォルト値を除外し、None
値を除外することによって、出力をカスタマイズすることができます。
Example - Serialization 3 ways
from 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"}
さらなる学習
documentation on serializationを参照してください。
JSON Schema¶
JSON Schemaは、任意のPydanticスキーマに対して生成することができ、APIの自己文書化と、JSONスキーマをサポートするさまざまなツールとの統合できます。
Example - JSON Schema
from datetime import datetime
from pydantic import BaseModel
class Address(BaseModel):
street: str
city: str
zipcode: str
class Meeting(BaseModel):
when: datetime
where: Address
why: str = 'No idea'
print(Meeting.model_json_schema())
"""
{
'$defs': {
'Address': {
'properties': {
'street': {'title': 'Street', 'type': 'string'},
'city': {'title': 'City', 'type': 'string'},
'zipcode': {'title': 'Zipcode', 'type': 'string'},
},
'required': ['street', 'city', 'zipcode'],
'title': 'Address',
'type': 'object',
}
},
'properties': {
'when': {'format': 'date-time', 'title': 'When', 'type': 'string'},
'where': {'$ref': '#/$defs/Address'},
'why': {'default': 'No idea', 'title': 'Why', 'type': 'string'},
},
'required': ['when', 'where'],
'title': 'Meeting',
'type': 'object',
}
"""
Pydanticは、OpenAPI 3.1と互換性のある標準の最新バージョンであるJSON Schema version 2020-12を生成します。
さらなる額十
documentation on JSON Schemaを参照ください。
Strict mode and data coercion¶
デフォルトでは、Pydanticは一般的な不正な型に対して耐性があり、データを正しい型に強制します。例えば、int
フィールドに渡された数値文字列はint
として解析します。
Pydanticには"strict=True"モードもあります。これは"Strictモード"とも呼ばれ、型が強制されず、入力データがスキーマや型のヒントと正確に一致しない限り、検証エラーが発生します。
しかし、strictモードはJSONデータを検証するときにはほとんど役に立たないでしょう。なぜなら、JSONにはdatetime
、UUID
、bytes
のような多くの一般的なpython型と一致する型がないからです。
これを解決するために、Pydanticは1つのステップでJSONを解析して検証することができます。これにより、RFC3339(別名ISO8601)文字列のような適切なデータ変換をdatetime
オブジェクトにすることができます。JSON解析はRustで実装されているため、非常にパフォーマンスに優れています。
Example - Strict mode that's actually useful
from 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'
さらなる学習
documentation on strict modeを参照してください。
Dataclasses, TypedDicts, and more¶
Pydanticは、スキーマを作成し、検証とシリアライズを実行するための4つの方法を提供しています。
BaseModel
— Pydantic独自のスーパークラスには、インスタンスメソッドを介して利用できる多くの共通ユーティリティがあります。pydantic.dataclasses.dataclass
— データクラスの初期化時に検証を実行する標準データクラスのラッパです。TypeAdapter
— 任意の型を検証とシリアライゼーションに適応させる一般的な方法です。これにより、TypedDict
やNamedTuple
のような型を検証することができます。また、int
やtimedelta
— all typesサポートをTypeAdapter
で使用することもできます。validate_call
— 関数を呼び出すときに検証を実行するデコレータです。
Example - schema based on TypedDict
from 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
はTypedDict
が検証を行うためのもので、validate_json
を使ってJSONデータを直接検証することもできます。
2. dump_python
はTypedDict
をpythonオブジェクトにシリアライズしますが、dump_json
でJSONにシリアライズすることもできます。
3. TypeAdapter
はJSONスキーマも生成できます。
Customisation¶
関数型バリデーターとシリアライザ、そしてカスタム型用の強力なプロトコルは、Pydanticの動作方法をフィールド単位または型単位でカスタマイズできます。
Customisation Example - wrap validators
"wrap validators" are new in Pydantic V2 and are one of the most powerful ways to customize Pydantic validation.
from datetime import datetime, timezone
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)
さらなる学習
validators, custom serializers, and custom typesを参照ください。
Ecosystem¶
この記事の執筆時点で、GitHubには214,100のリポジトリがあり、PyPIにはPydanticに依存する8,119のパッケージがあります。
Pydanticに依存している注目すべきライブラリをいくつか紹介します。
私家版訳注
以下は、翻訳時点のものです。(2024/07)
huggingface/transformers
107,475 starstiangolo/fastapi
60,355 starshwchase17/langchain
54,514 starsapache/airflow
30,955 starsmicrosoft/DeepSpeed
26,908 starsray-project/ray
26,600 starslm-sys/FastChat
24,924 starsLightning-AI/lightning
24,034 starsOpenBB-finance/OpenBBTerminal
22,785 starsgradio-app/gradio
19,726 starspola-rs/polars
18,587 starsmindsdb/mindsdb
17,242 starsRasaHQ/rasa
16,695 starsmlflow/mlflow
14,780 starsheartexlabs/label-studio
13,634 starsspotDL/spotify-downloader
12,124 starsSanster/lama-cleaner
12,075 starsairbytehq/airbyte
11,174 starsopenai/evals
11,110 starsmatrix-org/synapse
11,071 starsydataai/ydata-profiling
10,884 starspyodide/pyodide
10,245 starstiangolo/sqlmodel
10,160 starslucidrains/DALLE2-pytorch
9,916 starspynecone-io/reflex
9,679 starsPaddlePaddle/PaddleNLP
9,663 starsaws/serverless-application-model
9,061 starsmodin-project/modin
8,808 starsgreat-expectations/great_expectations
8,613 starsdagster-io/dagster
7,908 starsNVlabs/SPADE
7,407 starsbrycedrennan/imaginAIry
7,217 starschroma-core/chroma
7,127 starslucidrains/imagen-pytorch
7,089 starssqlfluff/sqlfluff
6,278 starsdeeppavlov/DeepPavlov
6,278 starsautogluon/autogluon
5,966 starsbridgecrewio/checkov
5,747 starsbentoml/BentoML
5,275 starsreplicate/cog
5,089 starsvitalik/django-ninja
4,623 starsapache/iceberg
4,479 starsjina-ai/discoart
3,820 starsembedchain/embedchain
3,493 starsskypilot-org/skypilot
3,052 starsPrefectHQ/marvin
2,985 starsmicrosoft/FLAML
2,569 starsdocarray/docarray
2,353 starsaws-powertools/powertools-lambda-python
2,198 starsNVIDIA/NeMo-Guardrails
1,830 starsroman-right/beanie
1,299 starsart049/odmantic
807 stars
Pydanticを使用している他のライブラリは、Kludex/awesome-pydantic
にあります。
Pydanticを使用している組織¶
Pydanticを使用しているいくつかの有名な企業や組織と、彼らがPydanticを使用していることを私たちが知っている理由/方法についてコメントします。
以下の組織は、以下の基準の1つ以上に一致しています。
- pydanticをパブリックリポジトリの依存関係として使用していること。
- 組織からpydanticドキュメントサイトへの参照トラフィック-一般的にパブリックドメインではないため、内部のドメイン固有の参照者は含まれません。
- 組織内でのPydanticの使用に関する、Pydanticチームと組織に属するエンジニアとの間で直接的なコミュニケーションを行っていること
We've included some extra detail where appropriate and already in the public domain. 必要に応じて詳細を追加しましたが、すでにパブリック・ドメインになっています。
私家版訳注
以下は、翻訳時点のものです。(2024/07)
Adobe¶
adobe/dy-sql
uses Pydantic.
Amazon and AWS¶
- powertools-lambda-python
- awslabs/gluonts
- AWS sponsored Samuel Colvin $5,000 to work on Pydantic in 2022
Anthropic¶
anthropics/anthropic-sdk-python
uses Pydantic.
Apple¶
(Based on the criteria described above)
ASML¶
(Based on the criteria described above)
AstraZeneca¶
Multiple repos in the AstraZeneca
GitHub org depend on Pydantic.
Cisco Systems¶
- Pydantic is listed in their report of Open Source Used In RADKit.
cisco/webex-assistant-sdk
Comcast¶
(Based on the criteria described above)
Datadog¶
- Extensive use of Pydantic in
DataDog/integrations-core
and other repos - Communication with engineers from Datadog about how they use Pydantic.
Facebook¶
Multiple repos in the facebookresearch
GitHub org depend on Pydantic.
GitHub¶
GitHub sponsored Pydantic $750 in 2022
Google¶
Extensive use of Pydantic in google/turbinia
and other repos.
HSBC¶
(Based on the criteria described above)
IBM¶
Multiple repos in the IBM
GitHub org depend on Pydantic.
Intel¶
(Based on the criteria described above)
Intuit¶
(Based on the criteria described above)
Intergovernmental Panel on Climate Change¶
Tweet explaining how the IPCC use Pydantic.
JPMorgan¶
(Based on the criteria described above)
Jupyter¶
- The developers of the Jupyter notebook are using Pydantic for subprojects
- Through the FastAPI-based Jupyter server Jupyverse
- FPS's configuration management.
Microsoft¶
- DeepSpeed deep learning optimisation library uses Pydantic extensively
- Multiple repos in the
microsoft
GitHub org depend on Pydantic, in particular their - Pydantic is also used in the
Azure
GitHub org - Comments on GitHub show Microsoft engineers using Pydantic as part of Windows and Office
Molecular Science Software Institute¶
Multiple repos in the MolSSI
GitHub org depend on Pydantic.
NASA¶
Multiple repos in the NASA
GitHub org depend on Pydantic.
NASA are also using Pydantic via FastAPI in their JWST project to process images from the James Webb Space Telescope, see this tweet.
Netflix¶
Multiple repos in the Netflix
GitHub org depend on Pydantic.
NSA¶
The nsacyber/WALKOFF
repo depends on Pydantic.
NVIDIA¶
Mupltiple repos in the NVIDIA
GitHub org depend on Pydantic.
Their "Omniverse Services" depends on Pydantic according to their documentation.
OpenAI¶
OpenAI use Pydantic for their ChatCompletions API, as per this discussion on GitHub.
Anecdotally, OpenAI use Pydantic extensively for their internal services.
Oracle¶
(Based on the criteria described above)
Palantir¶
(Based on the criteria described above)
Qualcomm¶
(Based on the criteria described above)
Red Hat¶
(Based on the criteria described above)
Revolut¶
Anecdotally, all internal services at Revolut are built with FastAPI and therefore Pydantic.
Robusta¶
The robusta-dev/robusta
repo depends on Pydantic.
Salesforce¶
Salesforce sponsored Samuel Colvin $10,000 to work on Pydantic in 2022.
Starbucks¶
(Based on the criteria described above)
Texas Instruments¶
(Based on the criteria described above)
Twilio¶
(Based on the criteria described above)
Twitter¶
Twitter's the-algorithm
repo where they
open sourced
their recommendation engine uses Pydantic.
UK Home Office¶
(Based on the criteria described above)