The header is 16 bytes and all its numbers are little-endian. It says which bytecode the file holds, and how Python can tell whether the file is still up to date with its source. The code object starts at offset 16.
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 2 | magic | Which bytecode the file holds |
| 2 | 2 | 0D 0A | A carriage return and a line feed |
| 4 | 4 | flags | 0, 1 or 3 |
| 8 | 4 | source_mtime | The source’s modification time, when flags is 0 |
| 12 | 4 | source_size | The source’s size in bytes, when flags is 0 |
| 8 | 8 | source_hash | A hash of the source, when flags is 1 or 3 |
Files with magic 3390 or 3391, from the alphas before PEP 552 went in, have no flags
field: source_mtime is at offset 4, source_size at offset 8 and
the code object at offset 12.
Magic number
A 16-bit number, then the bytes 0D 0A. CPython changes the number
whenever its bytecode changes, and only loads a file whose number is its own. The
carriage return and line feed mean that a file copied in text mode, which alters line
endings, no longer has the right magic number.
3394 is the final number of CPython 3.7, and the others belong to alpha and beta builds. The descriptions are those of the list in CPython’s source.
| Magic | Bytes | Release | What changed |
|---|---|---|---|
| 3390 | 3E 0D | 3.7a1 | Added LOAD_METHOD and CALL_METHOD |
| 3391 | 3F 0D | 3.7a2 | Updated GET_AITER |
| 3392 | 40 0D | 3.7a4 | PEP 552: deterministic .pyc files, with the flags field |
| 3393 | 41 0D | 3.7b1 | Removed STORE_ANNOTATION |
| 3394 | 42 0D | 3.7 (from 3.7b5) | Restored the docstring as the first statement in the body, which might affect the first line number |
Flags
A 32-bit number that says how the file is checked against its source, added by PEP 552. Bit 0 means the file holds a hash of the source and not its date and size. Bit 1 means the hash must be compared with the source when the file is loaded.
| Value | Kind | What Python does |
|---|---|---|
| 0 | Date and size | Compares source_mtime and source_size with the source file, and recompiles if either differs |
| 1 | Unchecked hash | Loads the file without looking at the source |
| 3 | Checked hash | Hashes the source and compares it with source_hash |
Bits above bit 1 are reserved, and CPython refuses a file that has any of them set.
The value 2 is not written by CPython, and the explorer treats it as invalid.
py_compile and compileall choose the kind with their
--invalidation-mode option. The interpreter’s
--check-hash-based-pycs option can override the check when the file is
loaded.
Source modification time
At offset 8 when flags is 0: the source file’s modification time when it was compiled, as a 32-bit count of seconds since 1 January 1970. Python compares only the low 32 bits.
Source size
At offset 12 when flags is 0: the size of the source file in bytes, modulo 232.
Source hash
At offset 8 when flags is 1 or 3: eight bytes taking the place of the date and the size. It is a 64-bit SipHash of the source file’s contents, keyed by the magic number, as PEP 552 sets out. The explorer shows it as one little-endian 64-bit number.
File names
Python writes these files to a __pycache__ folder next to the source
and puts the interpreter’s name and version in the file name.
| Source | Compiled by | File |
|---|---|---|
spam.py | CPython 3.7 | __pycache__/spam.cpython-37.pyc |
spam.py | CPython 3.7 with -O | __pycache__/spam.cpython-37.opt-1.pyc |
spam.py | CPython 3.7 with -OO | __pycache__/spam.cpython-37.opt-2.pyc |
A spam.pyc placed in a folder by itself, with no source file beside it,
can also be imported.