Binary Data with struct

The struct module converts between Python values and compact C-style bytes, letting you pack numbers into binary and unpack raw bytes from files, packets, and devices.

Learn Binary Data with struct in our free Python course — an interactive lesson with runnable examples, a practice exercise and a quick reference.

Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

When you need to read a binary file header or speak a wire protocol, struct is the precise, byte-accurate tool — a tiny format string describes exactly how the bytes are laid out.

struct.pack(fmt, *values) writes values into a bytes object; struct.unpack(fmt, data) reads them back as a tuple. The format string describes the layout — here means two shorts and a long, all big-endian:

The first character of a format sets byte order . The same number 1 packs to different bytes depending on endianness, which is why you must always be explicit when parsing a real format:

Network protocols and many file formats use big-endian ( or ! ). Pick one and stick with it across pack and unpack.

Real binary formats start with a fixed header : a magic signature, a version, and some counts. struct.calcsize(fmt) tells you how many bytes that header occupies, so you know exactly how much to read:

Fill in each ___ so the format string is big-endian and the round-trip prints the original values. (Hint: H = unsigned short, I = unsigned int.)

A device emits a stream of fixed-size records: an id ( H ) and a reading ( f ), big-endian. Pack three of them, then loop through the bytes calcsize at a time to unpack each record.

Lesson complete — you speak binary now!

You can pack values into bytes and unpack them back, read format characters like i , h , f , and s , control endianness with , use calcsize to measure layouts, and walk a binary stream record by record.

🚀 Up next: text wrapping & formatting — make long text readable with the textwrap module.

Practice quiz

What does the struct module do?

  • Defines C-style structs as Python classes
  • Compresses Python objects to disk
  • Converts between Python values and C-style packed bytes
  • Parses JSON into objects

Answer: Converts between Python values and C-style packed bytes. struct packs Python values into compact bytes and unpacks bytes back into values using a format string.

What does struct.unpack always return?

  • A tuple, even for one value
  • A single value
  • A list
  • A dictionary

Answer: A tuple, even for one value. unpack returns a tuple even for a single value: struct.unpack('>i', data) gives (5,), so index [0] or unpack it.

What does the '<' prefix mean in a format string?

  • Big-endian
  • Network byte order
  • Native with padding
  • Little-endian

Answer: Little-endian. '<' is little-endian (least significant byte first); '>' and '!' are big-endian, '=' is native order.

Which prefix means network byte order?

  • <
  • !
  • =
  • @

Answer: !. '!' is network byte order, which is the same as big-endian ('>').

What is the size of the format '>4sHI' according to struct.calcsize?

  • 10
  • 7
  • 8
  • 12

Answer: 10. 4s (4) + H (2) + I (4) = 10 bytes, since the explicit byte-order prefix removes padding.

What does the 'f' format character represent?

  • A 2-byte short
  • An 8-byte double
  • A 4-byte float
  • A flag bit

Answer: A 4-byte float. 'f' is a 4-byte float; 'd' is an 8-byte double, 'h' a 2-byte short, 'i' a 4-byte int.

Why do you get bytes back instead of a str from an 's' format?

  • struct only works on numbers
  • struct works at the byte level, so you decode text yourself
  • It is a bug in struct
  • The encoding was wrong

Answer: struct works at the byte level, so you decode text yourself. The 's' code yields a bytes object; decode it yourself with .decode('utf-8') or 'ascii' when you know the encoding.

What does struct.pack('>H', 258) produce?

  • b'\x02\x01'
  • b'\x00\x00'
  • b'258'
  • b'\x01\x02'

Answer: b'\x01\x02'. 258 is 0x0102; big-endian writes the most significant byte first, giving b'\x01\x02'.

What does struct.unpack('>i', b'\x00\x01') raise?

  • Nothing — it returns (1,)
  • A struct.error, because the buffer must be 4 bytes
  • A TypeError
  • A UnicodeDecodeError

Answer: A struct.error, because the buffer must be 4 bytes. The 'i' format needs exactly 4 bytes; a 2-byte buffer raises struct.error. Match the buffer to calcsize(fmt).

Why should you always include a byte-order prefix in a format string?

  • It makes packing faster
  • It is required syntax
  • Without one, native order plus padding can give surprising sizes
  • It enables compression

Answer: Without one, native order plus padding can give surprising sizes. No prefix means native byte order with alignment padding, so sizes vary by platform; a prefix gives exact, portable layouts.