В повседневных задачах есть множество инструментов для работы с различными форматами данных, такими как JSON, TOML, YAML и другими.
msgspec
— это инструмент, который может работать со всеми этими форматами и при этом быть быстрым и простым в использовании. Для всех форматов один импорт, что в рамках работы с данной библиотекой является преимуществом. Если вам необходимо парсить много разных форматов данных, то эта библиотека точно подойдет вам.
Библиотека содержит:
-
Высокопроизводительные кодеры/декодеры для распространенных протоколов: JSON, MessagePack, YAML и TOMI.
-
Поддержка большого количества типов данных.
-
Быстрая валидация данных
-
Структуры, позволяющие представлять данные (похожие на attrs/pydantic, но работают быстрее)
Для начала установим библиотеку:
pip3 install "msgspec[toml,yaml]"
Без дополнительных параметров библиотека установится с поддержкой json и messagepack.
Сериализация / десериализация
Для сериализации и десериализации данных нужен формат данных и входное значение.
import msgspec a = {"1": 2, "3": 4} encoded_json_data = msgspec.json.encode(a) print(encoded_json_data) # b'{"1": 2, "3": 4}' decoded_data = msgspec.json.decode(encoded_json_data) print(decoded_data) # {'1': 2, '3': 4} yaml_data = msgspec.yaml.encode(a) print(yaml_data) # b"'1': 2\n'3': 4\n"
Можно сделать вывод, что достаточно написать msgspec.{format}.[encode/decode]
, где format это json
, yaml
, toml
, msgpack
.
Валидация
Для валидации данных предлагается создавать классы, наследуясь от msgspec.Struct
, аналогичные как в attrs/dataclsses/pydantic.
class User(msgspec.Struct): name: str surname: str email: str | None = None print(msgspec.json.decode(b'{"name":"vasya","surname":"pupkin"}', type=User)) # User(name='vasya', surname='pupkin', email=None) print(msgspec.json.decode(b'{"name":"vasya","surname":123}', type=User)) # print(msgspec.json.decode(b'{"name":"vasya","surname":123}', type=User)) # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # msgspec.ValidationError: Expected `str`, got `int` - at `$.surname`
Добавляется только аргумент type
, который определяет схему.
Бенчмарки
Сравним msgspec по скорости с самыми популярными библиотеками сериализации:
Для этого берем большие файлы и для каждого кейса прогоняем тысячу раз, сравниваем среднее время
Входные данные
tests = [ # JSON { "msgspec.json.decode(data)": {"data": json_text}, "json.loads(data)": {"data": json_text}, }, { "msgspec.json.encode(data)": {"data": json_data}, "json.dumps(data)": {"data": json_data}, }, { "msgspec.json.decode(data)": {"data": json_text}, "orjson.loads(data)": {"data": json_text}, }, { "msgspec.json.encode(data)": {"data": json_data}, "orjson.dumps(data)": {"data": json_data}, }, # TOML { "msgspec.toml.decode(data)": {"data": toml_text}, "toml.loads(data)": {"data": toml_text}, }, { "msgspec.toml.decode(data)": {"data": toml_text}, "tomllib.loads(data)": {"data": toml_text}, }, { "msgspec.toml.encode(data)": {"data": toml_data}, "toml.dumps(data)": {"data": toml_data}, }, # YAML { "msgspec.yaml.decode(data)": {"data": yaml_text}, "yaml.load(data, Loader=yaml.Loader)": { "data": yaml_text, }, }, { "msgspec.yaml.decode(data)": {"data": yaml_text}, "yaml.load(data, Loader=yaml.CLoader)": { "data": yaml_text, }, }, { "msgspec.yaml.encode(data)": {"data": yaml_data}, "yaml.dump(data, Dumper=yaml.Dumper)": { "data": yaml_data, }, }, { "msgspec.yaml.encode(data)": {"data": yaml_data}, "yaml.dump(data, Dumper=yaml.CDumper)": { "data": yaml_data, }, }, ]
Тест |
Время (мс) |
Msgspec (мс) |
Ускорение |
json.loads(data) |
707.8 |
315.4 |
2.2 |
json.dumps(data) |
946.4 |
118.6 |
8.0 |
orjson.loads(data) |
306.2 |
315.7 |
1.0 |
orjson.dumps(data) |
83.9 |
118.2 |
0.7 |
toml.loads(data) |
1,017.9 |
420.0 |
2.4 |
tomllib.loads(data) |
420.4 |
420.2 |
1.0 |
toml.dumps(data) |
154.0 |
170.3 |
0.9 |
yaml.load(data, Loader=yaml.Loader) |
16,142.7 |
1,602.5 |
10.1 |
yaml.load(data, Loader=yaml.CLoader) |
1,625.4 |
1,603.1 |
1.0 |
yaml.dump(data, Dumper=yaml.Dumper) |
10,032.0 |
1,595.4 |
6.3 |
yaml.dump(data, Dumper=yaml.CDumper) |
1,600.5 |
1,594.8 |
1.0 |
Можно сделать вывод, что под капотом у библиотеки лучшие парсеры. Если вы пользуетесь только json, то стоит присмотреться к другой библиотеке (например, orjson), но все же значения библиотек не сильно критично разнятся. Также на примере yaml msgspec использует стандартные C имплементации.
Кроме того, есть бенчмарки от создателей библиотеки, которые сравнивают скорость сериализации и валидации данных.
Если в вашем коде требуется работа с различными форматами данных, например ваша программа принимает конфиг в yaml, поднимает API, которое отдаёт json и при этом не завязана на какой-нибудь pydantiс, то вам стоит попробовать msgspec. Также у библиотеки есть плюшки в виде json схем.
ссылка на оригинал статьи https://habr.com/ru/articles/830098/
Добавить комментарий