Struct and binary data ====================== The :mod:`struct` module packs Python values into a fixed binary layout and unpacks bytes back into Python values. Reach for it when working with a binary file format, a network protocol, or a device that exchanges fixed-size records. Two functions cover most cases: * :func:`struct.pack` -- take Python values and a *format string*, return a :class:`bytes` object of the exact layout. * :func:`struct.unpack` -- take a format string and a :class:`bytes` object, return a tuple of Python values. Format strings -------------- A format string lists one *code* per field in the record. The codes describe both the size and the interpretation of each field. Python's :class:`int` has no fixed size -- it grows to fit whatever value you assign. Binary formats *do* have fixed sizes: every integer field uses an agreed number of bytes. :mod:`struct` converts between unbounded Python ints and these fixed-size representations. An integer's *width* is the number of bits it uses. One byte is eight bits. The lowercase code is the signed variant; the uppercase code is the unsigned one (only non-negative values): * ``b`` / ``B`` -- **8-bit** (one byte). ``-128..127`` signed, ``0..255`` unsigned. * ``h`` / ``H`` -- **16-bit** (two bytes). ``-32768..32767`` signed, ``0..65535`` unsigned. * ``i`` / ``I`` -- **32-bit** (four bytes). About ±two billion signed, four billion unsigned. * ``q`` / ``Q`` -- **64-bit** (eight bytes). Effectively unbounded for everyday use. Pick a width that comfortably covers the range you expect. Packing a value outside the declared range either silently wraps around or raises :exc:`struct.error`, depending on the build. The remaining common codes are for floats and byte strings: * ``f`` -- 32-bit float (single precision; about seven decimal digits). Python's regular :class:`float` on MicroPython is already this size, so packing one into ``f`` is lossless. * ``d`` -- 64-bit float (double precision; about fifteen decimal digits). Packing a 32-bit MicroPython :class:`float` into ``d`` widens it to eight bytes but adds no precision. * ``s`` -- fixed-length byte string, preceded by a count (``8s`` for an eight-byte field). Byte order ---------- A multi-byte integer can be stored in memory two ways. The number ``0x12345678`` in a 32-bit field is laid out like this: * **Little-endian** -- least significant byte first: ``78 56 34 12``. * **Big-endian** -- most significant byte first: ``12 34 56 78``. Both encode the same value; they only disagree on which end of the field is the low byte. A file written by one system is garbled when read by the other if the byte order does not match. The leading character of the format string picks the order: * ``<`` -- little-endian. Common on x86 and ARM. * ``>`` -- big-endian. Common in network protocols. * ``!`` -- network order, equivalent to ``>``. Without a leading character, native byte order and native alignment are used; setting ``<`` or ``>`` explicitly removes that ambiguity and is usually what you want when reading a file or talking to another machine. .. note:: The OpenMV Cam is **little-endian** -- the same as its host PC. Use ``<`` in format strings for camera-local files and for binary data that travels to or from a desktop. Use ``>`` (or ``!``) for network protocols and for any format whose specification calls for big-endian. .. figure:: ../figures/struct-layout.svg :alt: Six bytes laid out in a row, with the first two bytes grouped as an "H" field (16-bit unsigned) and the next four as an "I" field (32-bit unsigned), each labelled with their little-endian byte order. ``"