Зачем использовать проверку данных с помощью Pydantic?¶
Сегодня Pydantic ежемесячно скачивают множество раз, а используют его одни из крупнейших и наиболее известных организаций в мире.
Трудно точно сказать, почему с момента появления Pydantic шесть лет назад он завоевал такую популярность, но можно выдвинуть несколько предположений.
Использование аннотаций типов для проверки схемы¶
Схема, на соответствие которой Pydantic выполняет проверку, как правило, определяется с помощью аннотаций типов (type hints) Python.
Аннотации типов отлично подходят для этой задачи: если вы пишете код на современном Python, то наверняка уже умеете ими пользоваться. Кроме того, благодаря использованию аннотаций типов Pydantic хорошо сочетается со средствами статического анализа кода (например, mypy и Pyright), а также с различными IDE (такими как PyCharm и VSCode).
Пример — только подсказки типов
from typing import Annotated, Literal
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)]}
- Поле
nameпросто помечено типомstr— допустима любая строка. - Тип [
Literal][typing.Literal] используется для того, чтобы ограничить возможные значения поляcolorвариантами'red'или'green'. - Даже если требуется наложить ограничения, не предусмотренные стандартными типами Python, можно воспользоваться [
Annotated][typing.Annotated] и библиотекойannotated-types— это позволит задать нужные условия, сохранив при этом поддержку типизации. - Я не утверждаю, что «bazam» — это действительно свойство фрукта; этот пример лишь показывает, что можно легко проверять корректность типов любой сложности.
Узнать больше
Производительность¶
Основная логика валидации в Pydantic реализована в отдельном пакете (pydantic-core),
в котором проверка большинства типов выполнена на языке Rust.
Благодаря этому Pydantic является одной из самых быстрых библиотек для валидации данных в Python.
Пример производительности — Pydantic против специализированного кода
Как правило, специализированный код должен работать значительно быстрее, чем универсальный валидатор, однако в данном примере Pydantic оказывается более чем на 300% быстрее специализированного кода при синтаксическом разборе JSON и проверке URL-адресов.
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 также предлагает отличные возможности для настройки валидации с помощью функциональных валидаторов.
Узнать больше
Сэмюэль Колвин в докладе на PyCon 2023 объясняет, как работает pydantic-core
и как он интегрируется с Pydantic.
Сериализация¶
Pydantic предоставляет возможность сериализации модели тремя способами:
- В словарь Python (
dict), состоящий из соответствующих объектов Python. - В словарь Python (
dict), состоящий только из типов, поддерживающих сериализацию в JSON. - В JSON-строку.
Во всех трех режимах результат можно настроить: исключить определенные поля, поля, которые не были заданы, значения по умолчанию, а также значения None.
Пример — 3 способа сериализации
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 схема¶
Для любой схемы Pydantic можно сгенерировать JSON схему, что позволяет создавать самодокументируемые API и обеспечивает интеграцию с широким спектром инструментов, поддерживающих формат JSON Schema.
Пример - JSON схема
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 соответствует последней версии спецификации JSON схемы (2020-12), которая совместима с OpenAPI 3.1.
Узнать больше
Смотри documentation on JSON Schema.
Строгий режим и приведение типов данных¶
По умолчанию Pydantic не допускает распространенных неправильных типов и приводит данные к правильному типу —
например числовая строка, переданная в поле int, будет анализироваться как int.
В Pydantic также есть строгий режим, где типы не приводятся и ошибка проверки возникает, если входные данные точно не соответствуют ожидаемой схеме.
Но строгий режим был бы совершенно бесполезен при проверке данных JSON, поскольку JSON не имеет совпадающих типов.
многие распространенные типы Python, такие как [datetime][datetime.datetime], [UUID][uuid.UUID] или [bytes][].
Чтобы решить эту проблему, Pydantic может анализировать и проверять JSON за один шаг. Это позволяет разумно преобразовывать данные.
(например, при анализе строк в объекты [datetime][datetime.datetime]). Поскольку анализ JSON
реализован на Rust, он также очень эффективен.
Пример — строгий режим, который действительно полезен
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, и многое другое¶
Pydantic предлагает четыре способа создания схем, а также выполнения валидации и сериализации:
BaseModel— базовый класс Pydantic, предоставляющий множество полезных инструментов, доступных через методы экземпляра.- Pydantic dataclasses — обертка над стандартными классами данных (dataclasses), дополненная механизмами валидации.
- [
TypeAdapter][pydantic.type_adapter.TypeAdapter] — универсальный инструмент для адаптации любого типа данных к процессам валидации и сериализации. Он позволяет выполнять валидацию как для таких структур, какTypedDictиNamedTuple, так и для простых типов (например, [int][] или [timedelta][datetime.timedelta]). С помощью [TypeAdapter][pydantic.type_adapter.TypeAdapter] можно работать со всеми типами, поддерживаемыми Pydantic. validate_call— декоратор, обеспечивающий валидацию данных при вызове функции.
Пример — схема на основе [TypedDict][typing.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',
}
"""
- [
TypeAdapter][pydantic.type_adapter.TypeAdapter] для [TypedDict][typing.TypedDict] выполняет проверку данных (валидацию); кроме того, он позволяет проверять JSON-данные напрямую с помощью метода [validate_json][pydantic.type_adapter.TypeAdapter.validate_json]. - Метод [
dump_python][pydantic.type_adapter.TypeAdapter.dump_python] используется для сериализации [TypedDict][typing.TypedDict] в объект Python; также возможна сериализация в формат JSON с помощью метода [dump_json][pydantic.type_adapter.TypeAdapter.dump_json]. - [
TypeAdapter][pydantic.type_adapter.TypeAdapter] также может генерировать JSON-схему (JSON Schema).
Настройка¶
Благодаря функциональным валидаторам и сериализаторам, а также мощному протоколу для пользовательских типов, поведение Pydantic можно гибко настраивать — как для отдельных полей, так и для целых типов данных.
Пример настройки — обертки для валидаторов
«Wrap-валидаторы» — это нововведение в Pydantic V2; они представляют собой один из самых мощных инструментов для настройки процесса валидации.
from datetime import datetime, timezone
from typing import Any
from pydantic_core.core_schema import ValidatorFunctionWrapHandler
from pydantic import BaseModel, field_validator
class Meeting(BaseModel):
when: datetime
@field_validator('when', mode='wrap')
def when_now(
cls, input_value: Any, handler: ValidatorFunctionWrapHandler
) -> datetime:
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(3600))
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)
Узнать больше
Смотри документацию по валидаторам, пользовательским сериализаторам, и пользовательским типам.
Экосистема¶
На момент написания этого текста в GitHub насчитывается 466 400 репозиториев, а в PyPI — 8 119 пакетов, зависящих от Pydantic.
Вот некоторые известные библиотеки, использующие Pydantic:
Некоторые примечательные библиотеки, зависящие от Pydantic:
huggingface/transformers138,570 звездhwchase17/langchain99,542 звездtiangolo/fastapi80,497 звездapache/airflow38,577 звездlm-sys/FastChat37,650 звездmicrosoft/DeepSpeed36,521 звездOpenBB-finance/OpenBBTerminal35,971 звездgradio-app/gradio35,740 звездray-project/ray35,176 звездpola-rs/polars31,698 звездLightning-AI/lightning28,902 звездmindsdb/mindsdb27,141 звездembedchain/embedchain24,379 звездpynecone-io/reflex21,558 звездheartexlabs/label-studio20,571 звездSanster/lama-cleaner20,313 звездmlflow/mlflow19,393 звездRasaHQ/rasa19,337 звездspotDL/spotify-downloader18,604 звездchroma-core/chroma17,393 звездairbytehq/airbyte17,120 звездopenai/evals15,437 звездtiangolo/sqlmodel15,127 звездydataai/ydata-profiling12,687 звездpyodide/pyodide12,653 звездdagster-io/dagster12,440 звездPaddlePaddle/PaddleNLP12,312 звездmatrix-org/synapse11,857 звездlucidrains/DALLE2-pytorch11,207 звездgreat-expectations/great_expectations10,164 звездmodin-project/modin10,002 звездaws/serverless-application-model9,402 звездsqlfluff/sqlfluff8,535 звездreplicate/cog8,344 звездautogluon/autogluon8,326 звездlucidrains/imagen-pytorch8,164 звездbrycedrennan/imaginAIry8,050 звездvitalik/django-ninja7,685 звездNVlabs/SPADE7,632 звездbridgecrewio/checkov7,340 звездbentoml/BentoML7,322 звездskypilot-org/skypilot7,113 звездapache/iceberg6,853 звездdeeppavlov/DeepPavlov6,777 звездPrefectHQ/marvin5,454 звездNVIDIA/NeMo-Guardrails4,383 звездmicrosoft/FLAML4,035 звездjina-ai/discoart3,846 звездdocarray/docarray3,007 звездaws-powertools/powertools-lambda-python2,980 звездroman-right/beanie2,172 звездart049/odmantic1,096 звезд
Больше библиотек, использующих Pydantic, можно найти в репозитории Kludex/awesome-pydantic.
Команда разработчиков Pydantic также создает Pydantic Logfire — платформу для обеспечения наблюдаемости (observability) с нативной интеграцией Pydantic, предназначенную для трассировки и отладки процессов валидации в рабочей среде (production).
Организации, использующие Pydantic¶
Ниже представлены некоторые известные компании и организации, использующие Pydantic, а также пояснения о том, почему или откуда нам известно об этом использовании.
Организации включены в этот список, если они соответствуют одному или нескольким из следующих критериев:
- Используют Pydantic в качестве зависимости в публичном репозитории.
- Направляют трафик на документацию Pydantic с домена, принадлежащего организации (конкретные источники переходов не указываются, так как эта информация, как правило, не является публичной).
- Осуществляли прямое общение с командой Pydantic по поводу использования библиотеки внутри своей организации.
Там, где это уместно и информация уже находится в открытом доступе, мы добавили дополнительные подробности.
Adobe¶
adobe/dy-sql использует Pydantic.
Amazon и AWS¶
- powertools-lambda-python
- awslabs/gluonts
- AWS спонсировала Сэмюэла Колвина на $5,000 для работы над Pydantic в 2022 году
Anthropic¶
anthropics/anthropic-sdk-python использует Pydantic.
Apple¶
(На основании критериев, описанных выше)
ASML¶
(На основании критериев, описанных выше)
AstraZeneca¶
Многие репозитории в организации AstraZeneca на GitHub зависят от Pydantic.
Cisco Systems¶
- Pydantic упоминается в их отчёте Программное обеспечение с открытым исходным кодом, используемое в RADKit.
cisco/webex-assistant-sdk
Capital One¶
(На основании критериев, описанных выше)
Comcast¶
(На основании критериев, описанных выше)
Datadog¶
- Широкое использование Pydantic в
DataDog/integrations-coreи других репозиториях. - Общение с инженерами Datadog о том, как они применяют Pydantic.
Facebook¶
Несколько репозиториев в организации facebookresearch на GitHub зависят от Pydantic.
GitHub¶
В 2022 году GitHub предоставил Pydantic спонсорскую поддержку в размере 750 долларов.
Google¶
Активное использование Pydantic в google/turbinia и других репозиториях.
HSBC¶
(На основании критериев, описанных выше)
IBM¶
Ряд репозиториев в организации IBM на GitHub зависят от Pydantic.
Intel¶
(На основании критериев, описанных выше)
Intuit¶
(На основании критериев, описанных выше)
Intergovernmental Panel on Climate Change¶
Твит объяснение того, как МГЭИК использует Pydantic.
JPMorgan¶
(На основании критериев, описанных выше)
Jupyter¶
- Разработчики Jupyter Notebook используют Pydantic в своих подпроектах.
- В Jupyverse — сервере для Jupyter, построенном на базе FastAPI.
- В системе управления конфигурациями FPS.
Microsoft¶
- Библиотека для оптимизации глубокого обучения DeepSpeed активно использует Pydantic.
- Pydantic применяется во многих репозиториях, принадлежащих организации
microsoftна GitHub. - Pydantic также используется в организации
Azureна GitHub. - В комментариях на GitHub можно увидеть, что инженеры Microsoft применяют Pydantic при разработке Windows и Office.
Molecular Science Software Institute¶
Ряд репозиториев в организации MolSSI на GitHub зависят от Pydantic.
NASA¶
Ряд репозиториев в организации NASA на GitHub зависят от Pydantic.
NASA также использует Pydantic (через FastAPI) в проекте JWST для обработки изображений, полученных с космического телескопа «Джеймс Уэбб»; см. этот твит.
Netflix¶
Ряд репозиториев в организации Netflix на GitHub зависят от Pydantic.
NSA¶
Репозиторий nsacyber/WALKOFF зависит от Pydantic.
NVIDIA¶
Ряд репозиториев в организации NVIDIA на GitHub зависят от Pydantic.
Согласно их документации, их «Omniverse Services» зависят от Pydantic.
OpenAI¶
Как следует из этого обсуждения на GitHub, OpenAI использует Pydantic в своем API ChatCompletions.
По имеющимся сведениям, OpenAI также активно применяет Pydantic в своих внутренних сервисах.
Oracle¶
(На основании критериев, описанных выше)
Palantir¶
(На основании критериев, описанных выше)
Qualcomm¶
(На основании критериев, описанных выше)
Red Hat¶
(На основании критериев, описанных выше)
Revolut¶
По имеющимся сведениям, все внутренние сервисы в Revolut построены с использованием FastAPI и, следовательно, Pydantic.
Robusta¶
Репозиторий robusta-dev/robusta зависит от Pydantic.
Salesforce¶
В 2022 году компания Salesforce выделила Сэмюэлу Колвину 10 000 долларов на работу над Pydantic.
Starbucks¶
(На основании критериев, описанных выше)
Texas Instruments¶
(На основании критериев, описанных выше)
Twilio¶
(На основании критериев, описанных выше)
Twitter¶
В репозитории Twitter the-algorithm, где компания
открыла исходный код
своего механизма рекомендаций, используется Pydantic.
UK Home Office¶
(На основании критериев, описанных выше)