AI Skill Report Card

Working with Binary Data

A-88·Aug 14, 2026·Source: Web
14 / 15
Python
import struct # Pack integers into binary data (big-endian, 2 ints) packed = struct.pack('>2i', 1, 2) # b'\x00\x00\x00\x01\x00\x00\x00\x02' # Unpack binary data back to Python values values = struct.unpack('>2i', packed) # (1, 2) # Serialize any Python object with pickle import pickle data = pickle.dumps({'key': 'value', 'nums': [1, 2, 3]}) obj = pickle.loads(data)
Recommendation
Add an example showing a bad outcome (e.g., pickling untrusted data causing security issue) to reinforce pitfalls concretely
14 / 15

Choose the right module based on the task:

Progress:

  • Identify data source/target: fixed-format binary (C structs, network protocols) vs. arbitrary Python objects
  • Choose module: struct for binary layouts, pickle for object serialization, shelve for persistent dict-like storage, marshal only for internal .pyc use (never for untrusted/external data)
  • For custom classes with pickle, implement __reduce__ or register with copyreg if default pickling fails
  • Define format strings (struct) or protocol version (pickle)
  • Handle byte order, size, and alignment explicitly for struct
  • Never unpickle data from untrusted sources — treat like eval()

struct — Binary layouts

Format strings define byte order + field types:

CharByte orderSize/align
@nativenative, aligned (default)
=nativestandard, no align
<little-endianstandard, no align
>big-endianstandard, no align
!network (big-endian)standard, no align

Common format codes: b/B (signed/unsigned char), h/H (short), i/I (int), l/L (long), q/Q (long long), f/d (float/double), s (char array), ? (bool).

Python
struct.pack('<3sB', b'abc', 255) # bytes with prefix count struct.calcsize('>4i') # size in bytes without packing struct.unpack_from(buffer, offset=0) # unpack from a slice of a larger buffer

Use struct.Struct(fmt) when reusing the same format repeatedly — precompiles it for speed.

pickle — Object serialization

Python
with open('data.pkl', 'wb') as f: pickle.dump(obj, f, protocol=pickle.HIGHEST_PROTOCOL) with open('data.pkl', 'rb') as f: obj = pickle.load(f)
  • Use pickle.HIGHEST_PROTOCOL unless cross-version compatibility is required.
  • Not all objects are picklable by default (open files, sockets, lambdas, some C extension objects). Implement __getstate__/__setstate__ or __reduce__ on the class.

copyreg — Extending pickle for classes you don't control

Python
import copyreg def pickle_point(p): return (Point, (p.x, p.y)) copyreg.pickle(Point, pickle_point)

shelve — Persistent dict-backed storage

Python
import shelve with shelve.open('mydata') as db: db['key'] = {'complex': 'object'} value = db['key']

Values are pickled automatically; keys must be strings.

marshal — Internal use only

Reserved for Python's own .pyc bytecode serialization. Not stable across versions, not safe for untrusted input. Do not use for application-level serialization — use pickle instead.

Recommendation
Include a struct.Struct precompiled example to match the 'use Struct for hot loops' advice with actual code
17 / 20

Example 1: Parsing a binary file header Input: A binary file starts with a 4-byte magic number, 2-byte version (uint16), 4-byte length (uint32), all big-endian. Output:

Python
import struct HEADER_FMT = '>4sHI' HEADER_SIZE = struct.calcsize(HEADER_FMT) # 10 bytes with open('file.bin', 'rb') as f: magic, version, length = struct.unpack(HEADER_FMT, f.read(HEADER_SIZE))

Example 2: Caching computed results to disk across runs Input: An expensive function whose results should persist between program executions, keyed by input string. Output:

Python
import shelve def get_cached(key, compute_fn): with shelve.open('cache.db') as db: if key not in db: db[key] = compute_fn(key) return db[key]

Example 3: Deep-copying a complex nested object graph Input: An object with circular references and custom classes that needs a full deep copy. Output:

Python
import pickle def deep_copy(obj): return pickle.loads(pickle.dumps(obj))
Recommendation
Consider a brief section comparing pickle vs json for when serialization needs to be interoperable or human-readable
  • Prefer explicit byte order (<, >, !) over @/native to ensure portability across machines.
  • Use struct.Struct objects for repeated pack/unpack in hot loops.
  • Always open files in binary mode ('rb'/'wb') when working with struct or pickle.
  • For network protocols, use ! (network byte order = big-endian) by convention.
  • Version your pickle protocol explicitly in long-lived storage formats to control forward/backward compatibility.
  • Use shelve for simple persistent key-value needs; use sqlite3 or a database for anything requiring queries or concurrent access.
  • Never pickle.load() untrusted or unauthenticated data — arbitrary code execution risk, equivalent to eval().
  • Forgetting struct alignment/padding differences between @ (native, padded) and </>/= (no padding) causes size mismatches.
  • Mixing up format string repeat counts, e.g. '3s' (one 3-byte string) vs 'sss' (three 1-byte strings).
  • Using marshal for application data persistence — it's undocumented/unstable across Python versions.
  • Forgetting shelve requires closing (or using with) to flush writes to disk.
  • Assuming all Python objects are picklable by default — sockets, file handles, generators, and some lambdas are not.
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
14/15
Examples
17/20
Completeness
18/20
Format
15/15
Conciseness
14/15