{"id":1969,"library":"construct","title":"construct Binary Data Parser","description":"construct is a powerful declarative symmetric parser/builder for binary data, supporting Python 3.6+. It allows you to define the structure of binary data using Python objects and then parse or build data according to that structure. The current version is 2.10.70, and it maintains a fairly active release cadence, often releasing minor fixes and improvements.","status":"active","version":"2.10.70","language":"en","source_language":"en","source_url":"https://github.com/construct/construct","tags":["binary data","parser","builder","serialization","deserialization","protocol","struct"],"install":[{"cmd":"pip install construct","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"note":"Old import path for construct versions prior to 2.5/2.6. Modern construct uses top-level imports.","wrong":"from construct.core import Struct","symbol":"Struct","correct":"from construct import Struct"},{"symbol":"Int8ub","correct":"from construct import Int8ub"},{"symbol":"Bytes","correct":"from construct import Bytes"},{"symbol":"Array","correct":"from construct import Array"},{"symbol":"GreedyRange","correct":"from construct import GreedyRange"},{"symbol":"StreamError","correct":"from construct import StreamError"}],"quickstart":{"code":"from construct import Struct, Int8ub, Bytes, Array, GreedyRange, StreamError\n\n# Define a simple binary structure\n# A header, an array of 8-bit unsigned integers, and a variable-length data block\npacket_struct = Struct(\n    \"header\" / Bytes(4), # 4-byte header\n    \"count\" / Int8ub,    # 1-byte count of following integers\n    \"data\" / Array(lambda ctx: ctx.count, Int8ub), # Array of 'count' integers\n    \"payload\" / GreedyRange(Int8ub) # Remaining bytes as a list of integers\n)\n\n# Example data to build\nmy_data = {\n    \"header\": b\"\\xde\\xad\\xbe\\xef\",\n    \"count\": 3,\n    \"data\": [10, 20, 30],\n    \"payload\": [1, 2, 3, 4, 5]\n}\n\n# Build binary data from Python object\nbuilt_binary = packet_struct.build(my_data)\nprint(f\"Built binary: {built_binary.hex()}\")\n\n# Parse binary data into Python object\n# Using a different example binary for parsing\nbinary_to_parse = b\"\\xaa\\xbb\\xcc\\xdd\\x02\\x01\\x02\\xff\\xee\\xdd\"\n\ntry:\n    parsed_object = packet_struct.parse(binary_to_parse)\n    print(f\"Parsed object: {parsed_object}\")\n\n    # Accessing fields\n    print(f\"Parsed header: {parsed_object.header.hex()}\")\n    print(f\"Parsed data: {parsed_object.data}\")\nexcept StreamError as e:\n    print(f\"Error parsing data: {e}\")","lang":"python","description":"This quickstart demonstrates how to define a `Struct` using various constructors like `Bytes`, `Int8ub`, `Array`, and `GreedyRange`. It shows how to use lambda functions within a structure definition to refer to previously parsed fields (e.g., `ctx.count`). Finally, it illustrates building Python objects into binary data and parsing binary data back into Python objects, including basic error handling."},"warnings":[{"fix":"Migrate your code to the modern construct API (2.8+ is recommended). This will likely involve a complete rewrite of your structure definitions and parsing/building logic. Refer to the official construct documentation for the current API.","message":"Major API overhaul occurred between construct 2.0 and 2.5/2.6. This was a near-complete rewrite, deprecating and removing many constructs (e.g., `Buffer`, `BitStruct`), changing import paths (`construct.core`), and modifying core behaviors. Code written for construct 2.0 is highly unlikely to work with 2.5+.","severity":"breaking","affected_versions":"< 2.5"},{"fix":"Review the changelog for versions 2.8 and 2.9. Update `Subconstruct` usage to directly use the base construct, rename `RepeatUntil` to `GreedyRange`, and adjust conditional error handling if `Context.error_when` was used.","message":"Breaking changes were introduced in versions 2.8 and 2.9. Notably, `Subconstruct` was removed in 2.8 (use `Construct` directly), `RepeatUntil` was renamed to `GreedyRange`, and `Context.error_when` behavior changed slightly in 2.9.","severity":"breaking","affected_versions":">= 2.8"},{"fix":"If you need to reuse a construct with different parameters or ensure isolation, create a new instance each time, or use `construct.deep_copy` if you're modifying a complex, nested structure and need a true independent copy.","message":"Construct objects (e.g., `Struct`, `Array`) are often mutable. If you create an instance of a construct and then modify its internal properties or reuse it in different contexts without care, you might encounter unexpected side effects due to shared state.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Thoroughly understand the `Context` object and how `this` (or `ctx`) dynamically refers to the current parsing/building context. Debug with `construct.Probe` to inspect the context at various points in your structure definition. Ensure fields are defined before they are referenced via `this`.","message":"The `this` (or `ctx`) variable, used for accessing context and previously parsed fields within `lambda` functions or methods, can be a source of confusion. Misunderstanding its scope or when certain fields become available can lead to errors.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}