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.15. 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. Some instructions are followed by inline
caches. Python 3.15 writes marshal version 6, which can store frozen
dictionaries, and its instructions carry the settings of lazy imports.
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.15 releases write 3666.
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: 3666, 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.15 changed
The header, the order of the code object’s fields, the location table and the exception table are those of Python 3.14. The changes are in the objects and the instructions:
marshalversion 6 adds a type for the new built-infrozendict. A code object, slice or frozen dictionary can no longer be written if it contains itself.- The
lazy importstatement:IMPORT_NAMEkeeps its name index in arg>> 2, and its two low bits say whether the import is lazy or must be eager. GET_ITERtakes an argument and replacesGET_YIELD_FROM_ITER. A loop oryield fromnow keeps two items on the stack: an iterator and NULL, or the object itself and an index. This changes the stack ofFOR_ITER,SEND,END_SEND,POP_ITERandCLEANUP_THROW.RESUME,GET_ITERandCALL_FUNCTION_EXgain a one-unit inline cache.RESUME’s argument gains a value for the start of a generator expression.LOAD_COMMON_CONSTANTgrows from 5 to 12 objects, addinglist,set,None, the empty string,True,Falseand −1.TRACE_RECORDtakes 255 andENTER_EXECUTORmoves to 254. Most instructions fromGET_LENtoYIELD_VALUEare renumbered.
Every magic number of the 3.15 pre-releases is on the header page. No final release wrote those before 3666.
Telling it apart
The first two bytes, little-endian, are the magic number: 3650 to 3666, and 3666 in
every final 3.15 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.14 have the same layout but a magic number from 3600 to 3627,
marshal version 5, and number their instructions differently.
00000000 52 0E 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)
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.15)
- marshal – Python’s documentation of the module and its version numbers (Python 3.15)
- importlib – Python’s documentation of the import system (Python 3.15)
- 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
- code_objects.md – CPython’s description of the code object and the location table (Python 3.15)
- exception_handling.md – CPython’s description of the exception table (Python 3.15)
- pycore_magic_number.h – CPython’s list of magic numbers (Python 3.15)
- bytecodes.c – CPython’s definition of every instruction (Python 3.15)