Python Bytecode Generator and Modifier
The `bytecode` library is a Python module designed to generate, analyze, and modify Python bytecode. It provides an abstract representation of bytecode that can be manipulated and then converted back into executable code objects. Currently at version 0.17.0, it is actively maintained with a regular release cadence, often introducing support for new Python versions and associated bytecode changes.
Warnings
- breaking The structure of Python bytecode is an internal implementation detail of CPython and can change significantly between major Python versions. While `bytecode` aims to abstract this, code built for one Python version may behave differently or break on another due to underlying CPython changes, especially when generating bytecode that isn't fully generic.
- breaking The `bytecode` library's API has undergone changes to accommodate new CPython bytecode formats and features, particularly with Python 3.11, 3.13, and 3.14 support. For example, `BaseInstr` was removed and `Instr` became the base class in 0.17.0, and new enums are now used for certain opcode arguments (e.g., `BINARY_OP`, `CONVERT_VALUE`).
- gotcha Direct manipulation of bytecode is a low-level operation and requires a deep understanding of the Python Virtual Machine's stack-based execution model, opcode semantics, and operand types. Misinterpreting stack effects or opcode arguments can lead to incorrect or crashing bytecode.
Install
-
pip install bytecode
Imports
- Bytecode
from bytecode import Bytecode
- Instr
from bytecode import Instr
- ConcreteBytecode
from bytecode import ConcreteBytecode
- ControlFlowGraph
from bytecode import ControlFlowGraph
Quickstart
from bytecode import Instr, Bytecode
# Create bytecode for print('Hello World!')
bytecode_obj = Bytecode([
Instr('LOAD_GLOBAL', (True, 'print')), # Load the global 'print' function
Instr('LOAD_CONST', 'Hello World!'), # Load the string 'Hello World!'
Instr('CALL', 1), # Call 'print' with 1 argument
Instr('POP_TOP'), # Pop the return value (None) from the stack
Instr('LOAD_CONST', None), # Load None
Instr('RETURN_VALUE') # Return None
])
# Convert the bytecode object to a CPython code object
code = bytecode_obj.to_code()
# Execute the generated code
exec(code)