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.
Object types
Types are taken from CPython’s Python/marshal.c at the 2.3.7, 2.4.6,
2.5.6 and 2.7.18 tags. The last column says which releases write each type; a
.pyc file is written at the highest marshal version of the release that
makes it, which is 1 in 2.4 and 2 in 2.5 to 2.7.
| Byte | Name | What follows | Releases |
|---|---|---|---|
0 | TYPE_NULL | Nothing. Marks the end of a dictionary | All |
N | TYPE_NONE | Nothing. The value None | All |
F | TYPE_FALSE | Nothing. The value False | All |
T | TYPE_TRUE | Nothing. The value True | All |
S | TYPE_STOPITER | Nothing. The StopIteration exception | All |
. | TYPE_ELLIPSIS | Nothing. The value Ellipsis | All |
i | TYPE_INT | A signed 32-bit integer | All |
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 | All |
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 | All |
f | TYPE_FLOAT | One length byte, then the number written as ASCII text | 2.3, 2.4 |
g | TYPE_BINARY_FLOAT | An 8-byte little-endian IEEE 754 floating-point number | 2.5 on |
x | TYPE_COMPLEX | The real part as one length byte and ASCII text, then the imaginary part the same way | 2.3, 2.4 |
y | TYPE_BINARY_COMPLEX | Two 8-byte little-endian floating-point numbers, real then imaginary | 2.5 on |
s | TYPE_STRING | A signed 32-bit length, then that many bytes. Holds text, the bytecode and the line number table | All |
t | TYPE_INTERNED | Laid out like s. The string is added to the list of interned strings | 2.4 on |
R | TYPE_STRINGREF | A 32-bit index into that list | 2.4 on |
u | TYPE_UNICODE | A signed 32-bit length in bytes, then the text in UTF-8 | All |
( | TYPE_TUPLE | A signed 32-bit item count, then that many objects | All |
[ | TYPE_LIST | A signed 32-bit item count, then that many objects | All |
{ | TYPE_DICT | Key and value objects, in pairs, until a 0 byte where a key would be | All |
< | TYPE_SET | A signed 32-bit count, then that many objects | 2.5 on |
> | TYPE_FROZENSET | A signed 32-bit count, then that many objects | 2.5 on |
c | TYPE_CODE | The fields of a code object | All |
? 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.
Interned strings
Python 2.4 to 2.7 avoid storing the same interned string twice. The first time an
interned string is written, it gets the type byte t and is added to a list
kept for the whole file. Every later use of the same string is written as
R and its position in that list, counted from 0.
Reading works the same way: each t string is interned and added to the
list, and each R takes its string from the list. The list only holds these
strings. Python 2.3 has none of this and writes every string as s, and a
marshal version of 0 turns the scheme off.
Bytes no release here writes
The explorer’s reader is shared by every Python version, so it accepts these type bytes in any file. Python 2.3 to 2.7 neither write nor read them. The layouts are those later Pythons use.
| Byte | Name | Meaning here |
|---|---|---|
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 |
r | TYPE_REF | A 32-bit index of an earlier object that was saved |
: | TYPE_SLICE | Three objects: start, stop and step |