Первая модель

Установите bytespec в окружение с Python 3.10+:

python -m pip install bytespec

Этот пример можно сохранить в user.py и выполнить целиком:

from bytespec import ProtoModel

class User(ProtoModel):
    name: str
    active: bool

user = User(name="Anna", active=True)
encoded = user.encode()
decoded = User.decode(encoded)

print(decoded.name)    # Anna
print(decoded.active)  # True

Теперь разберём три действия из примера.

Описать и создать модель

User наследует ProtoModel. Аннотации name: str и active: bool описывают два поля сообщения. Для строк и логических значений дополнительная настройка не нужна.

Значения передаются по именам и доступны как атрибуты:

user = User(name="Boris", active=False)
print(user.name)  # Boris

Пока оба поля обязательны: их нужно передать при создании User. На следующей странице добавим значение по умолчанию.

Записать в bytes

encoded = user.encode()
print(type(encoded).__name__)  # bytes

encode() возвращает законченное бинарное сообщение. Его можно сохранить в файл или отправить по сети без преобразования в текст. После стандартного header записываются name и active в порядке объявления полей. Длину текста и всего тела сообщения библиотека вычисляет сама; вручную менять смещение или поддерживать отдельную функцию записи не нужно.

Прочитать обратно

decoded = User.decode(encoded)
print(decoded.name)    # Boris
print(decoded.active)  # False

decode() вызывается у класса и создаёт новый User. Передайте ему байты одного сообщения. Получатель должен знать его модель: библиотека не выбирает класс автоматически по содержимому.

Это весь цикл обычного использования: класс → экземпляр → bytes → экземпляр. Меняя поля или их настройки, согласуйте модель у отправителя и получателя.

Посмотреть на байты

У первой модели User(name="Anna", active=True) содержимое полей такое:

encoded = User(name="Anna", active=True).encode()
print(encoded[14:].hex(" "))
00 00 00 04 41 6e 6e 61 01

Четыре байта длины строки, UTF-8 Anna, затем 01 для True. Срез пропускает 14 байт стандартного header. Для другого протокола можно выбрать размер числа, префикс строки и само framing; это постепенно разбирается в Числа и другие типы, Строки, длины и настройки полей и Header и framing.

Далее — Поля и значения по умолчанию: сделаем active полем со значением по умолчанию.