The python interpreter converts programs to bytecodes before beginning execution. Execution itself consist of looping over these bytecodes and performing specific operations over each one. This talk gives a very brief overview of the main classes of bytecodes.
This presentation was given as a lightning talk at the Boston Python Meetup group on July 24th, 2012.
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
Python opcodes
1. The Python Interpreter is Fun and
Not At All Terrifying: Opcodes
name: Alex Golec
twitter: @alexandergolec
not @alexgolec : (
email: akg2136 (rhymes with cat) columbia dot (short for education)
this talk lives at: blog.alexgolec.com
1
2. Python is Bytecode-Interpreted
• Your python program is compiled down to bytecode
• Sort of like assembly for the python virtual machine
• The interpreter executes each of these bytecodes one by one
2
3. Before we Begin
• This presentation was written using the CPython 2.7.2 which ships with
Mac OS X Mountain Lion GM Image
• The more adventurous among you will find that minor will details differ
on PyPy / IronPython / Jython
3
4. The Interpreter is Responsible For:
• Issuing commands to objects and maintaining stack state
• Flow Control
• Managing namespaces
• Turning code objects into functions and classes
4
7. Example: Arithmetic Operations
>>> def parabola(x):
• We don’t know the type of x!
...
...
return x*x + 4*x + 4
• How does BINARY_MULTIPLY
>>> dis.dis(parabola)
2 0 LOAD_FAST 0 (x)
know how to perform
3 LOAD_FAST 0 (x) multiplication?
6 BINARY_MULTIPLY
•
7 LOAD_CONST 1 (4)
10 LOAD_FAST
13 BINARY_MULTIPLY
0 (x) What is I pass a string?
14 BINARY_ADD
15 LOAD_CONST
18 BINARY_ADD
1 (4)
• Note the lack of registers; the
19 RETURN_VALUE Python virtual machine is stack-
based
7
8. Things the Interpreter Doesn’t Do:
Typed Method Dispatch
• The python interpreter does not know anything about how to add
two numbers (or objects, for that matter)
• Instead, it simply maintains a stack of objects, and when it comes time
to perform an operation, asks them to perform the operation
• The result gets pushed onto the stack
8
12. Simple Namespaces
>>> def example():
... variable = 1
... def function():
... print 'function'
... del variable
... del function
...
>>> dis.dis(example)
2 0 LOAD_CONST 1 (1) • Variables, functions, etc. are all
3 STORE_FAST 0 (variable) treated identically
3 6 LOAD_CONST 2 (<code object b at 0x10c545930, file "<stdin>", line 3>)
•
9 MAKE_FUNCTION 0
12 STORE_FAST 1 (function) Once the name is assigned to the
5 15 DELETE_FAST 0 (variable) object, the interpreter completely
6 18 DELETE_FAST 1 (function)
forgets everything about it except
21 LOAD_CONST 0 (None) the name
24 RETURN_VALUE
12
14. Functions First!
>>> def square(inputfunc):
... def f(x):
... return inputfunc(x) * inputfunc(x)
... return f
...
>>> dis.dis(square)
2 0 LOAD_CLOSURE 0 (inputfunc)
3 BUILD_TUPLE 1
6 LOAD_CONST 1 (<code object f at 0x10c545a30, file "<stdin>", line 2>)
9 MAKE_CLOSURE 0
•
12 STORE_FAST 1 (f)
The compiler generates code
4 15 LOAD_FAST 1 (f)
18 RETURN_VALUE objects and sticks them in
memory
14
15. Now Classes!
>>> def make_point(dimension, names):
... class Point:
... def __init__(self, *data):
... pass
... dimension = dimensions
... return Point
...
>>> dis.dis(make_point)
2 0 LOAD_CONST 1 ('Point')
3 LOAD_CONST 3 (())
6 LOAD_CONST 2 (<code object Point at 0x10c545c30, file "<stdin>", line 2>)
9 MAKE_FUNCTION 0
12 CALL_FUNCTION 0
15 BUILD_CLASS BUILD_CLASS()
16 STORE_FAST 2 (Point)
6 19 LOAD_FAST 2 (Point) Creates a new class object. TOS is the methods
22 RETURN_VALUE dictionary, TOS1 the tuple of the names of the base
classes, and TOS2 the class name.
15
16. Other Things
• Exceptions
• Loops
• Technically flow control, but they’re a little more involved
16
24. >>> def list_get(lst, pos): • The exception context is pushed by
... try: SETUP_EXCEPT
...
...
return lst[pos]
except IndexError: • If an exception is thrown, control jumps to the
... return None
address of the top exception context, in this case
... # there is an invisible “return None” here opcode 15
>>> dis.dis(list_get)
2 0 SETUP_EXCEPT 12 (to 15) • If there is no top exception context, the
interpreter halts and notifies you of the error
3 3
6
LOAD_FAST
LOAD_FAST
0 (lst)
1 (pos)
• The yellow opcodes check if the exception thrown
matches the type of the one in the except
9 BINARY_SUBSCR
10 RETURN_VALUE statement, and execute the except block
11
12
POP_BLOCK
JUMP_FORWARD 18 (to 33) • At END_FINALLY, the interpreter is responsible for
popping the exception context, and either re-raising
4 >> 15 DUP_TOP the exception, in which case the next-topmost
16 LOAD_GLOBAL 0 (IndexError) exception context will trigger, or returning from the
19 COMPARE_OP 10 (exception match) function
22 POP_JUMP_IF_FALSE 32
25 POP_TOP • Notice that the red opcodes will never be executed
26
27
POP_TOP
POP_TOP • The first: between a return and a jump target
• The second: only reachable by jumping from dead
5 28 LOAD_CONST 0 (None) code.
31 RETURN_VALUE
>> 32 END_FINALLY • CPython’s philosophy of architectural and
>> 33 LOAD_CONST 0 (None) implementation simplicity tolerates such minor
36 RETURN_VALUE inefficiencies
24