Python Bytecode
Python is an interpreted language, but it also involves a compilation step. Python source code (.py) is first compiled into bytecode, which is a low-level, platform-independent set of instructions. This bytecode is then executed by the Python Virtual Machine (PVM).
The Compilation Process
- Source Code: You write Python code in
.pyfiles. - Bytecode: When you run the program, Python compiles the source code into bytecode. This bytecode is often cached in
.pycfiles inside the__pycache__directory to speed up subsequent loads. - PVM: The Python Virtual Machine reads the bytecode and executes the corresponding machine code instructions on your computer's CPU.
Viewing Bytecode
You can inspect the bytecode of Python functions or modules using the built-in dis module (Disassembler).
import dis
def add(a, b):
return a + b
dis.dis(add)
Output Example:
4 0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_ADD
6 RETURN_VALUE
For more details on the dis module, see programming/python/dis-module.
Understanding Instructions
Each line in the disassembly output represents a bytecode instruction:
- Line Number: The line number in the original source code.
- Address: The byte offset of the instruction in the bytecode sequence.
- Opcode: The name of the operation (e.g.,
LOAD_FAST,BINARY_ADD). - Argument: The argument for the operation, if any.
Code Objects
Bytecode is stored inside code objects. Every function in Python has a __code__ attribute that holds its code object.
def my_func():
pass
print(my_func.__code__)
# Output: <code object my_func at ...>
print(my_func.__code__.co_code)
# Output: b'd\x00S\x00' (The raw bytecode bytes)