Skip to main content

bytestruct

Python application Pypi version Docs

bytestruct parses and builds binary wire formats with the standard library alone. Fixed-size records are dataclasses whose field annotations give each field's wire type; variable-length data is described by small codecs that compose like construct's. Everything is fully typed.

The layout of a record is compiled into struct.Struct objects once, when the class is defined, so parsing a record is a single unpack_from per byte-order run.

Documentation: https://doronz88.github.io/bytestruct/, including a migration guide from construct.

Install

python3 -m pip install -U bytestruct

Fixed-size records

from dataclasses import dataclass, field
from enum import IntEnum
from typing import Annotated

from bytestruct import BinaryStruct, Const, PaddedString, u16, u32


class Kind(IntEnum):
    FILE = 1
    DIRECTORY = 2


@dataclass
class Header(BinaryStruct, byte_order="<"):
    magic: Annotated[u32, Const(0x1F3D5B79)] = field(default=0x1F3D5B79, init=False)
    size: u32
    name: Annotated[str, PaddedString(16)]
    kind: Annotated[Kind, u16]  # parsed into the enum type


data = Header(size=1024, name="notes.txt", kind=Kind.FILE).build()  # a bad value -> BinaryBuildError
header = Header.parse(data)  # short input -> TruncatedDataError, wrong magic -> UnexpectedConstantError
assert header.kind is Kind.FILE

Wire fields are positional __init__ parameters in wire order. A field declared = field(default=..., init=False) is left out of __init__: parse skips its bytes (padding) and build packs its default (on a Const field, the constant). Fields without a wire type may follow the wire fields and are ignored by parse/build. Records cannot be subclassed.

Available field types include u8..u64, i16..i64, byte-order pinned u32le/u32be, Bytes(n), PaddedString(n), uuid_t, ipv4/ipv6, Array(element, n), int-enum fields and Const magics; custom ones subclass Format.

Codecs

from bytestruct import CSTRING, U32_LE, U64_LE, Aligned, Prefixed, Switch

STRING = Aligned(4, Prefixed(U32_LE, CSTRING))  # u32 length, NUL-terminated UTF-8, padded to 4 bytes
OBJECT = Switch(U32_LE, {1: STRING, 2: U64_LE})  # parses to (tag, value)

assert OBJECT.parse(OBJECT.build((1, "hi"))) == (1, "hi")

A codec is anything with read(reader) and build(value): the combinators (Prefixed, Aligned, PrefixedArray, Tuple, Switch), the leaves (CSTRING, GREEDY_STRING, GREEDY_BYTES, PASS), the scalars (U8, U16_LE/U16_BE, ..., F64_BE), Bytes(n), and record classes themselves. A record field annotated with a codec (name: Annotated[str, CSTRING]) makes the record variable-length; such fields follow the fixed-size ones. Formats with no declarative shape are read by hand with ByteReader, whose sub-readers are windows on the same buffer (nothing is copied).

Errors

Every failure raises a BinaryDataError (a ValueError): BinaryParseError (with TruncatedDataError and UnexpectedConstantError) or BinaryBuildError. Errors carry the record, field, absolute offset and the path through nested codecs, and prefix their message with them:

Header.magic at offset 0: expected 0x1f3d5b79, got 0x0
DICTIONARY -> [2] -> STRING at offset 104: expected 200 bytes, found 16

License

MIT

Metadata

Release files for bytestruct 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bytestruct 0.1.0
File Size Uploaded
bytestruct-0.1.0.tar.gz 62.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bytestruct 0.1.0
File Interpreter ABI Platform
bytestruct-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 78.8 kB

Release files / bytestruct-0.1.0.tar.gz

Download URL bytestruct-0.1.0.tar.gz
Size 62.1 kB
Tags Source
SHA-256 checksum
How to use checksums
9b85d66423f5180749c992b69fec2bc6f2523b0d18b570e6939d575241473603
BLAKE2b-256 checksum
How to use checksums
ead8c29ba8a62df86d7de6d558414a30f31e477072ea78b80958df9462dd1993
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / bytestruct-0.1.0-py3-none-any.whl

Download URL bytestruct-0.1.0-py3-none-any.whl
Size 16.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
21e9794842503ae3bac6287e7f3692dee950b1a9a71b2513d4bfaf2f0a4bd358
BLAKE2b-256 checksum
How to use checksums
c2b725cad4df0a15b317efe8c323f3ba6a7330acad1a3932540742a2d58abd8b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page