Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

Python Bytecode: Fun with dis - Allison Kaptur

3/29/15

Allison Kaptur
An occasional blog on programming
Navigate

Search

AUG 14TH, 2013

Python Bytecode: Fun With Dis


Last week at Hacker School I did a quick presentation on python bytecode and the
module. The disassembler is a very powerful tool with a gentle learning curve
that is, you can get a fair amount out of it without really knowing much about whats
going on. This post is a quick introduction to how and why you should use it.
dis

Whats bytecode?
Bytecode is the internal representation of a python program in the compiler. Here,
well be looking at bytecode from cpython, the default compiler. If you dont know
what compiler youre using, its probably cpython.

How do I get bytecode?


You already have it! Bytecode is whats contained in those .pyc files you see when
you import a module. Its also created on the fly by running any python code.

Disassembling
Ok, so you have some bytecode, and you want to understand it. Lets look at it
without using the dis module first.
1
2
3
4
5
6
7
8
9
10
11

>>> def foo():


...
a=2
...
b=3
...
return a + b
...
>>> foo.func_code
<code object foo at 0x106353530, file "<stdin>", line 1>
>>> foo.func_code.co_code
'd\x01\x00}\x00\x00d\x02\x00}\x01\x00|\x00\x00|\x01\x00\x17S'
>>> print [ord(x) for x in foo.func_code.co_code]
[100, 1, 0, 125, 0, 0, 100, 2, 0, 125, 1, 0, 124, 0, 0, 124, 1, 0, 23, 83]

http://akaptur.com/blog/2013/08/14/python-bytecode-fun-with-dis/

1/4

Python Bytecode: Fun with dis - Allison Kaptur

3/29/15

Hmm, that was not very enlightening. We can see that we have a bunch of bytes
(some printable, others not), but we have no idea what they mean.
Lets run it through dis.dis instead.
1
2
3
4
5
6
7
8
9
10
11
12

>>> import dis


>>> dis.dis(foo)
2
0 LOAD_CONST
3 STORE_FAST
3

6 LOAD_CONST
9 STORE_FAST
12 LOAD_FAST
15 LOAD_FAST
18 BINARY_ADD
19 RETURN_VALUE

1 (2)
0 (a)
2 (3)
1 (b)
0 (a)
1 (b)

Now this starts to make some sense. dis takes each byte, finds the opcode that
corresponds to it in opcodes.py , and prints it as a nice, readable constant. If we look
at opcodes.py we see that LOAD_CONST is 100, STORE_FAST is 125, etc. dis also shows
the line numbers on the left and the values or names on the right. So without ever
seeing something like before, we have an idea whats going on: we first load a
constant, 2, then somehow store it as a . Then we repeat this with 3 and b . We load
and b back up, do BINARY_ADD , which presumably adds the numbers, and then
do RETURN_VALUE .
a

Examining the bytecode can sometimes increase your understanding of python


code. Here is one example.

elif
elif

1
2
3
4
5
6
7
8
9
10
11
12
13

is identical in bytecode to else ... if . Take a look:

>>> def flat(num):


...
if num % 3 == 0:
...
print "Fizz"
...
elif num % 5 == 0:
...
print "Buzz"
...
else:
...
print num
>>>
>>> def nested(num):
...
if num % 3 == 0:
...
print "Fizz"
...
else:
...
if num % 5 == 0:

http://akaptur.com/blog/2013/08/14/python-bytecode-fun-with-dis/

2/4

Python Bytecode: Fun with dis - Allison Kaptur

14
15
16

...
...
...

3/29/15

print "Buzz"
else:
print num

Weve read PEP 8 so we know that flat is better than nested for style and readability.
But is there a performance difference? Not at all in fact, these two functions have
identical bytecode.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

0 LOAD_FAST
0 (num)
3 LOAD_CONST
1 (3)
6 BINARY_MODULO
7 LOAD_CONST
2 (0)
10 COMPARE_OP
2 (==)
13 POP_JUMP_IF_FALSE
24

16 LOAD_CONST
19 PRINT_ITEM
20 PRINT_NEWLINE
21 JUMP_FORWARD

>> 24 LOAD_FAST
27 LOAD_CONST
30 BINARY_MODULO
31 LOAD_CONST
34 COMPARE_OP
37 POP_JUMP_IF_FALSE

3 ('Fizz')

29 (to 53)
0 (num)
4 (5)
2 (0)
2 (==)
48

40 LOAD_CONST
43 PRINT_ITEM
44 PRINT_NEWLINE
45 JUMP_FORWARD

5 ('Buzz')

>> 48 LOAD_FAST
51 PRINT_ITEM
52 PRINT_NEWLINE
>> 53 LOAD_CONST
56 RETURN_VALUE

0 (num)

5 (to 53)

0 (None)

That makes sense else just means start executing here if the if was false
theres no more computation to do. elif is just syntactic sugar.

Further reading:
This just scratches the surface of whats interesting about python bytecode.
If you enjoyed this, you might enjoy diving into Yaniv Aknins series on python
internals. If youre excited about bytecode, you should contribute to Ned
Batchelders byterun.
http://akaptur.com/blog/2013/08/14/python-bytecode-fun-with-dis/

3/4

Python Bytecode: Fun with dis - Allison Kaptur

3/29/15

Posted by akaptur Aug 14th, 2013 python


Tweet

Systematic Debugging

Bug hunting

Recent Posts
PS1 for Python3
I'm joining Dropbox
Debugging with pstree
Rejected PyCon Proposals
Getting Started with Python Internals

Copyright 2014 - akaptur - Powered by Octopress - Theme by Gehaxelt and IT Solutions Neef

http://akaptur.com/blog/2013/08/14/python-bytecode-fun-with-dis/

4/4

You might also like