Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Валидация и сериализация в 2023 году

Валидация и сериализация в 2023 году

Небольшая преза на тему pydantic, и его скоростного конкурента msgspec и небольшое их сравнение по скорости.

Denis Anikin

August 15, 2023
Tweet

More Decks by Denis Anikin

Other Decks in Programming

Transcript

  1. Денис Аникин 2 Что я делаю — работаю в Райфе

    — teamlead в 3 командах — community lead в Python Community — fullstack: typescript, python, devops https://xfenix.ru
  2. Pydantic 7 О плюсах —Очень популярная —Легкая, удобная —На скорость

    особых жалоб не было, но… —Ядро на расте (теперь) — х5 к скорости
  3. Pydantic 8 Как выглядит, если кто не видел class SomeUser(BaseModel):

    client_fio: str client_gender: tuple[int, ...] phone_of_mama: int card_balance: decimal.Decimal probability_of_fail: float ready_to_move_on: bool traits: tuple[ typing.Literal["immortality", "omniprecense", "omnipower", "superspeed"], ... ] music_he_hates: frozenset[ typing.Literal["kallyanni_rap", "hookah_pop", "rock", "jazz", "folk"] ]
  4. 12 Dataclasses from pydantic.dataclasses import dataclass @dataclass class User: id:

    int name: str = 'John Doe' signup_ts: datetime = None user = User(id='42', signup_ts='2032-06-21T12:00') print(user) """ User(id=42, name='John Doe', signup_ts=datetime.datetime(2032, 6, 21, 12, 0)) """
  5. 13 Validate_call from pydantic import ValidationError, validate_call @validate_call def repeat(s:

    str, count: int, *, separator: bytes = b'') -> bytes: ... try: c = repeat('hello', 'wrong') except ValidationError as exc: print(exc) """ 1 validation error for repeat 1 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='wrong', input_type=str] """
  6. 15 BaseSettings class Settings(BaseSettings): auth_key: str = Field(validation_alias='my_auth_key') redis_dsn: RedisDsn

    = Field( 'redis://user:pass@localhost:6379/1', validation_alias=AliasChoices('service_redis_dsn', 'redis_url'), )
  7. MsgSpec 20 Что там интересного —Zero-cost schema validation —Speedy Struct

    type for representing structured data —High performance encoders/decoders for common protocols. The JSON and MessagePack implementations regularly benchmark as the fastest options for Python
  8. Интересное по рантайм работе 25 —Быстро импортируются —Создание инстанса оглушительно

    быстрое (в 50 раз быстрее pydantic) —Сравнение от 6 до 500 раз быстрее других альтернатив —Сравнение больше, меньше и т.п. быстрее от 10 до 70 раз
  9. 30 Можно использовать как json декодер import msgspec # once

    msgspec.json.decode(b'{"hello":"world"}') # multiple decoder = msgspec.json.Decoder() decoder.decode(b'{"hello":"world"}')
  10. 31 Typed декодер! import msgspec class User(msgspec.Struct): name: str groups:

    set[str] = set() email: str | None = None msgspec.json.decode( b'{"name": "alice", "groups": ["admin", "engineering"]}', type=User ) msgspec.json.decode( b'{"name": "bill", "groups": ["devops", 123]}', type=User ) """ Traceback (most recent call last): File "<stdin>", line 1, in <module> msgspec.ValidationError: Expected `str`, got `int` - at `$.groups[1]` """
  11. 33 Struct — основная вещь import msgspec from typing import

    Set, Optional class User(msgspec.Struct): """A struct describing a user""" name : str email : Optional[str] = None groups : Set[str] = set()
  12. 34 Пример декодинга >>> class User2(msgspec.Struct): ... name: str ...

    groups: set[str] = set() ... email: str | None = None ... phone : str | None = None ... >>> new_dec = msgspec.json.Decoder(User2) >>> new_dec.decode('{"name": "kek", "groups": ["a", "b"], "email": "[email protected]", "phone": "+76661313"}') User2(name='kek', groups={'a', 'b'}, email='[email protected]', phone='+76661313')