Introduction
When CPython imports a module from a
.py file, it compiles the source to bytecode
and saves the result as a .pyc file in a __pycache__ folder
beside the source. The next import loads the .pyc file and skips the
compiler. The file holds the module’s code object: its instructions, constants and
names, with the code object of every function and class nested inside.
This page covers the format written by Python 3.13. Its code object keeps local, cell and free variables in one list, with a qualified name, a location table that records lines and columns, and an exception table. Instructions are two bytes, and some are followed by inline caches.
The magic number at the start of the file says which release wrote it, and a file only runs on a release with exactly the same number. The final Python 3.13 releases write 3571.
A .pyc file dropped on any page of this site opens in the explorer, which
shows its structure, a disassembly and each code object.
Structure
A file is a 16-byte header followed by one object in Python’s
marshal format, the module’s code object. All numbers are little-endian.
0magic: 3571, then0D 0A4 bytes4flags: 0 for a date check, 1 or 3 for a hash check4 bytes8source_mtime and source_size, or source_hash8 bytes16code object of the module, onemarshalobjectvaries
The code object holds counts, flags, the instructions as a byte string, a tuple of constants (which holds nested code objects), and tables of names, source positions and exception handlers.
What Python 3.13 changed
The header and the fields of the code object are those of Python 3.12. The changes are in the instructions:
- Every instruction has a new number. The numbers are generated from CPython’s
instruction definitions: those without an argument come first, in alphabetical
order from 1 to 44, those with an argument follow from 45 to 118, and
RESUMEis 149. - Conversion to
boolis explicit.TO_BOOLcomes before a conditional jump, andPOP_JUMP_IF_TRUE,POP_JUMP_IF_FALSEandUNARY_NOTexpect an exactbool.COMPARE_OPmoves its operator above bit 5 and uses bit 4 to ask for aboolresult. - Conditional jumps and
JUMP_BACKWARDare followed by an inline cache, as areTO_BOOLandCONTAINS_OP. CALL_KWreplacesKW_NAMES. For a call the stack holds the callable, thenselfor NULL, soLOAD_GLOBALandLOAD_ATTRpush the NULL orselfafter the value.MAKE_FUNCTIONtakes no argument;SET_FUNCTION_ATTRIBUTEsets defaults, annotations and the closure one at a time.- f-strings use
CONVERT_VALUE,FORMAT_SIMPLEandFORMAT_WITH_SPECinstead ofFORMAT_VALUE. LOAD_FAST_LOAD_FAST,STORE_FAST_LOAD_FASTandSTORE_FAST_STORE_FASTeach do the work of two instructions.LOAD_CLOSUREis no longer written; the compiler emitsLOAD_FAST.YIELD_VALUE’s argument says whether it belongs to ayield fromorawait, andRESUME’s argument gains a bit for except-depth 1.END_FORremoves one item instead of two.
Every magic number of the 3.13 pre-releases is on the header page.
Telling it apart
The first two bytes, little-endian, are the magic number: 3550 to 3571, and 3571 in
every final 3.13 release. The next two bytes are 0D 0A. The explorer takes
these numbers and then reads the file strictly: only 0, 1 and 3 are valid flags, and the
code object must fill the rest of the file exactly.
Files of Python 3.12 have the same layout but a magic number of 3500 to 3531, and number their instructions differently. Files of Python 3.14 have a magic number of 3600 or more.
00000000 F3 0D 0D 0A 00 00 00 00 00 F1 53 65 06 00 00 00
Variants
- Python 1.5 to 2.0 bytecode – 8-byte header, one or three-byte instructions and 16-bit numbers in the code object
- Python 2.1 and 2.2 bytecode – adds free and cell variables to the code object
- Python 2.3 to 2.7 bytecode – the code object’s numbers become 32-bit
- Python 3.0 to 3.2 bytecode – keyword-only arguments; text and bytes become separate types
- Python 3.3 to 3.5 bytecode – 12-byte header with the source size; object references from 3.4
- Python 3.6 bytecode – two-byte instructions
- Python 3.7 bytecode – 16-byte header with a flags field
- Python 3.8 and 3.9 bytecode – positional-only arguments
- Python 3.10 bytecode –
co_linetable, and jumps that count instructions - Python 3.11 bytecode – one list of locals, a location table, an exception table and inline caches
- Python 3.12 bytecode – inlined comprehensions, method loads folded into
LOAD_ATTR, forward-only conditional jumps - Python 3.13 bytecode – instructions renumbered, explicit conversion to
bool, caches on jumps - Python 3.14 bytecode –
marshalversion 5 with slice constants, small integers in the argument - Python 3.15 bytecode –
marshalversion 6, lazy imports and a cache onRESUME
Links
Software
- CPython – the Python interpreter, which writes and loads these files;
python -m disshows the bytecode (Windows, macOS, Linux) - Decompyle++ (pycdc) – disassembler and decompiler for
.pycfiles of many Python versions (Windows, macOS, Linux)
Developers
- dis – Python’s own bytecode disassembler (Python)
- marshal – Python’s own module for the object format of the body (Python)
- py_compile – Python’s own module that writes
.pycfiles (Python) - importlib – Python’s import system, which reads and checks them (Python)
- xdis – cross-version disassembler (Python)
Reference
- dis – Python’s documentation of its bytecode instructions (Python 3.13)
- marshal – Python’s documentation of the module and its version numbers (Python 3.13)
- importlib – Python’s documentation of the import system (Python 3.13)
- PEP 3147 – the
__pycache__folder and its file names - PEP 552 – the flags field and hash-based
.pycfiles - PEP 626 – precise line numbers for tracing
- PEP 657 – columns in the location table
- PEP 709 – inlined comprehensions
- locations.md – CPython’s description of the location table (Python 3.13)
- exception_handling_notes.txt – CPython’s description of the exception table (Python 3.13)
- _bootstrap_external.py – the importer, whose comments list every magic number (Python 3.13)