Everything after the header is one object in Python’s marshal format,
always the module’s code object. An object is one type byte followed by whatever that
type needs. Containers hold further objects, each with its own type byte. Every length
and number is little-endian. There is no index and no sharing, so finding an object
means reading everything before it.
Object types
Types are taken from CPython’s Python/marshal.c at the 2.1.3 and 2.2.3
tags.
| Byte | Name | What follows | Releases |
|---|---|---|---|
0 | TYPE_NULL | Nothing. Marks the end of a dictionary | Both |
N | TYPE_NONE | Nothing. The value None | Both |
S | TYPE_STOPITER | Nothing. The StopIteration exception | 2.2 |
. | TYPE_ELLIPSIS | Nothing. The value Ellipsis | Both |
i | TYPE_INT | A signed 32-bit integer | Both |
I | TYPE_INT64 | A signed 64-bit integer. Written by a Python whose C long is more than 32 bits wide, for a value that needs more than 32 bits | Both |
l | TYPE_LONG | A signed 32-bit count of digits, negative for a negative number, then that many unsigned 16-bit digits in base 32768, lowest digit first. Used for long integers | Both |
f | TYPE_FLOAT | One length byte, then the number written as ASCII text | Both |
x | TYPE_COMPLEX | The real part as one length byte and ASCII text, then the imaginary part the same way | Both |
s | TYPE_STRING | A signed 32-bit length, then that many bytes. Holds text, the bytecode itself and the line number table | Both |
u | TYPE_UNICODE | A signed 32-bit length in bytes, then the text in UTF-8 | Both |
( | TYPE_TUPLE | A signed 32-bit item count, then that many objects | Both |
[ | TYPE_LIST | A signed 32-bit item count, then that many objects | Both |
{ | TYPE_DICT | Key and value objects, in pairs, until a 0 byte where a key would be | Both |
c | TYPE_CODE | The fields of a code object | Both |
? is TYPE_UNKNOWN. CPython writes it for an object it
cannot marshal and reports an error, and does not read it back, so it does not occur
in a good file.
Bytes no release here writes
The explorer’s reader is shared by every Python version, so it accepts these type bytes in any file. Neither 2.1 nor 2.2 writes or reads them. The layouts are those later Pythons use, in case a damaged or hand-made file has one.
| Byte | Name | Meaning here |
|---|---|---|
F | TYPE_FALSE | The value False; nothing follows |
T | TYPE_TRUE | The value True; nothing follows |
g | TYPE_BINARY_FLOAT | An 8-byte floating-point number |
y | TYPE_BINARY_COMPLEX | Two 8-byte floating-point numbers, real then imaginary |
t | TYPE_INTERNED | Laid out like s |
R | TYPE_STRINGREF | A 32-bit index into the list of t strings |
a | TYPE_ASCII | A 32-bit length, then the text |
A | TYPE_ASCII_INTERNED | Laid out like a |
z | TYPE_SHORT_ASCII | One length byte, then the text |
Z | TYPE_SHORT_ASCII_INTERNED | Laid out like z |
) | TYPE_SMALL_TUPLE | One count byte, then that many objects |
< | TYPE_SET | A 32-bit count, then that many objects |
> | TYPE_FROZENSET | A 32-bit count, then that many objects |
r | TYPE_REF | A 32-bit index of an earlier object that was saved |
: | TYPE_SLICE | Three objects: start, stop and step |