SlideShare a Scribd company logo
Byterun:
A (C)Python interpreter in Python
Allison Kaptur
!
github.com/akaptur
akaptur.github.io
@akaptur
Byterun
with Ned Batchelder
!
Based on
# pyvm2 by Paul Swartz (z3p)
from http://www.twistedmatrix.com/users/z3p/
Why would you do such a thing
>>> if a or b:
... do_stuff()
Some things we can do
out = ""
for i in range(5):
out = out + str(i)
print(out)
Some things we can do
def fn(a, b=17, c="Hello", d=[]):
d.append(99)
print(a, b, c, d)
!
fn(1)
fn(2, 3)
fn(3, c="Bye")
fn(4, d=["What?"])
fn(5, "b", "c")
Some things we can do
def verbose(func):
def _wrapper(*args, **kwargs):
return func(*args, **kwargs)
return _wrapper
!
@verbose
def add(x, y):
return x+y
!
add(7, 3)
Some things we can do
try:
raise ValueError("oops")
except ValueError as e:
print("Caught: %s" % e)
print("All done")
Some things we can do
class NullContext(object):
def __enter__(self):
l.append('i')
return self
!
def __exit__(self, exc_type, exc_val, exc_tb):
l.append('o')
return False
!
l = []
for i in range(3):
with NullContext():
l.append('w')
if i % 2:
break
l.append('z')
l.append('e')
!
l.append('r')
s = ''.join(l)
print("Look: %r" % s)
assert s == "iwzoeiwor"
Some things we can do
g = (x*x for x in range(3))
print(list(g))
A problem
g = (x*x for x in range(5))
h = (y+1 for y in g)
print(list(h))
The Python virtual machine:
!
A bytecode interpreter
Bytecode:
the internal representation of a python
program in the interpreter
Bytecode: it’s bytes!
>>> def mod(a, b):
... ans = a % b
... return ans
Bytecode: it’s bytes!
>>> def mod(a, b):
... ans = a % b
... return ans
>>> mod.func_code.co_code
Function Code
object
Bytecode
Bytecode: it’s bytes!
>>> def mod(a, b):
... ans = a % b
... return ans
>>> mod.func_code.co_code
'|x00x00|x01x00x16}x02x00|x02x00S'
Bytecode: it’s bytes!
>>> def mod(a, b):
... ans = a % b
... return ans
>>> mod.func_code.co_code
‘|x00x00|x01x00x16}x02x00|x02x00S'
>>> [ord(b) for b in mod.func_code.co_code]
[124, 0, 0, 124, 1, 0, 22, 125, 2, 0, 124,
2, 0, 83]
dis, a bytecode disassembler
>>> import dis
>>> dis.dis(mod)
2 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 BINARY_MODULO
7 STORE_FAST 2 (ans)
!
3 10 LOAD_FAST 2 (ans)
13 RETURN_VALUE
dis, a bytecode disassembler
>>> import dis
>>> dis.dis(mod)
2 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 BINARY_MODULO
7 STORE_FAST 2 (ans)
!
3 10 LOAD_FAST 2 (ans)
13 RETURN_VALUE
Line
Number
Index in
bytecode Instruction
name, for
humans
More bytes, the
argument to each
instruction
Hint about
arguments
whatever
some other thing
something
whatever
some other thing
something
a
b
whatever
some other thing
something
ans
Before
After
BINARY_MODULO
After
LOAD_FAST
Data stack on a frame
def foo():
x = 1
def bar(y):
z = y + 2
return z
return bar(x)
foo() # <--- (1)
!
c
a
l
l
!
s
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: [<foo>]
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c
a
l
l ---------------------
| foo Frame | -> blocks: []
s | | -> data: [<bar>, 1]
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: []
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2 # <--- (3)
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c ---------------------
a | bar Frame | -> blocks: []
l | (newest) | -> data: [1, 2]
l ---------------------
| foo Frame | -> blocks: []
s | | -> data: []
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: []
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2 # <--- (3)
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c ---------------------
a | bar Frame | -> blocks: []
l | (newest) | -> data: [3]
l ---------------------
| foo Frame | -> blocks: []
s | | -> data: []
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: []
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2 # <--- (3)
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c
a
l
l ---------------------
| foo Frame | -> blocks: []
s | | -> data: [3]
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: []
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2 # <--- (3)
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c
a
l
l
!
s
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: [3]
k ---------------------
dis, a bytecode disassembler
>>> import dis
>>> dis.dis(mod)
2 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 BINARY_MODULO
7 STORE_FAST 2 (ans)
!
3 10 LOAD_FAST 2 (ans)
13 RETURN_VALUE
Allison Kaptur: Bytes in the Machine: Inside the CPython interpreter, PyGotham 2014
} /*switch*/
/* Main switch on opcode
*/
READ_TIMESTAMP(inst0);
!
switch (opcode) {
#ifdef CASE_TOO_BIG
default: switch (opcode) {
#endif
/* Turn this on if your compiler chokes on the big switch: */
/* #define CASE_TOO_BIG 1 */
Back to that bytecode
!
>>> dis.dis(mod)
2 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 BINARY_MODULO
7 STORE_FAST 2 (ans)
!
3 10 LOAD_FAST 2 (ans)
13 RETURN_VALUE
case LOAD_FAST:
x = GETLOCAL(oparg);
if (x != NULL) {
Py_INCREF(x);
PUSH(x);
goto fast_next_opcode;
}
format_exc_check_arg(PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
PyTuple_GetItem(co->co_varnames, oparg));
break;
case BINARY_MODULO:
w = POP();
v = TOP();
if (PyString_CheckExact(v))
x = PyString_Format(v, w);
else
x = PyNumber_Remainder(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
if (x != NULL) continue;
break;
It’s “dynamic”
>>> def mod(a, b):
... ans = a % b
... return ans
>>> mod(15, 4)
3
“Dynamic”
>>> def mod(a, b):
... ans = a % b
... return ans
>>> mod(15, 4)
3
>>> mod(“%s%s”, (“Py”, “Gotham”))
“Dynamic”
>>> def mod(a, b):
... ans = a % b
... return ans
>>> mod(15, 4)
3
>>> mod(“%s%s”, (“Py”, “Gotham”))
PyGotham
“Dynamic”
>>> def mod(a, b):
... ans = a % b
... return ans
>>> mod(15, 4)
3
>>> mod(“%s%s”, (“Py”, “Gotham”))
PyGotham
>>> print “%s%s” % (“Py”, “Gotham”)
PyGotham
case BINARY_MODULO:
w = POP();
v = TOP();
if (PyString_CheckExact(v))
x = PyString_Format(v, w);
else
x = PyNumber_Remainder(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
if (x != NULL) continue;
break;
>>> class Surprising(object):
… def __mod__(self, other):
… print “Surprise!”
!
>>> s = Surprising()
>>> t = Surprsing()
>>> s % t
Surprise!
“In the general absence of type information, almost
every instruction must be treated as
INVOKE_ARBITRARY_METHOD.”
!
- Russell Power and Alex Rubinsteyn, “How Fast Can
We Make Interpreted Python?”
Back to our problem
g = (x*x for x in range(5))
h = (y+1 for y in g)
print(list(h))
def foo():
x = 1
def bar(y):
z = y + 2
return z
return bar(x)
foo() # <--- (1)
!
c
a
l
l
!
s
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: [<foo>]
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c
a
l
l ---------------------
| foo Frame | -> blocks: []
s | | -> data: [<bar>, 1]
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: []
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2 # <--- (3)
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c ---------------------
a | bar Frame | -> blocks: []
l | (newest) | -> data: [1, 2]
l ---------------------
| foo Frame | -> blocks: []
s | | -> data: []
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: []
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2 # <--- (3)
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c ---------------------
a | bar Frame | -> blocks: []
l | (newest) | -> data: [3]
l ---------------------
| foo Frame | -> blocks: []
s | | -> data: []
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: []
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2 # <--- (3)
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c
a
l
l ---------------------
| foo Frame | -> blocks: []
s | | -> data: [3]
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: []
k ---------------------
def foo():
x = 1
def bar(y):
z = y + 2 # <--- (3)
return z
return bar(x) # <--- (2)
foo() # <--- (1)
!
c
a
l
l
!
s
t ---------------------
a | main (module) Frame | -> blocks: []
c | (oldest) | -> data: [3]
k ---------------------
Back to our problem
g = (x*x for x in range(5))
h = (y+1 for y in g)
print(list(h))
More
Great blogs
http://tech.blog.aknin.name/category/my-projects/
pythons-innards/ by @aknin
http://eli.thegreenplace.net/ by Eli Bendersky
!
Contribute! Find bugs!
https://github.com/nedbat/byterun
!
Apply to Hacker School!
www.hackerschool.com/apply

More Related Content

PDF
Bytes in the Machine: Inside the CPython interpreter
akaptur
 
PDF
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
akaptur
 
PDF
"A 1,500 line (!!) switch statement powers your Python!" - Allison Kaptur, !!...
akaptur
 
PDF
Diving into byte code optimization in python
Chetan Giridhar
 
PDF
Exploring slides
akaptur
 
PDF
Python opcodes
alexgolec
 
PPTX
TCO in Python via bytecode manipulation.
lnikolaeva
 
DOCX
Wap to implement bitwise operators
Harleen Sodhi
 
Bytes in the Machine: Inside the CPython interpreter
akaptur
 
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
akaptur
 
"A 1,500 line (!!) switch statement powers your Python!" - Allison Kaptur, !!...
akaptur
 
Diving into byte code optimization in python
Chetan Giridhar
 
Exploring slides
akaptur
 
Python opcodes
alexgolec
 
TCO in Python via bytecode manipulation.
lnikolaeva
 
Wap to implement bitwise operators
Harleen Sodhi
 

What's hot (20)

PDF
All I know about rsc.io/c2go
Moriyoshi Koizumi
 
PDF
Implementing Software Machines in C and Go
Eleanor McHugh
 
PDF
Introducción a Elixir
Svet Ivantchev
 
PDF
Faster Python, FOSDEM
Victor Stinner
 
PDF
Go a crash course
Eleanor McHugh
 
PPT
Python легко и просто. Красиво решаем повседневные задачи
Maxim Kulsha
 
PDF
Functional Programming inside OOP? It’s possible with Python
Carlos V.
 
PPTX
Load-time Hacking using LD_PRELOAD
Dharmalingam Ganesan
 
PDF
Playing 44CON CTF for fun and profit
44CON
 
PDF
Implementing Software Machines in Go and C
Eleanor McHugh
 
PPT
Whats new in_csharp4
Abed Bukhari
 
PDF
dplyr
Romain Francois
 
PDF
Phil Bartie QGIS PLPython
Ross McDonald
 
PDF
Metarhia KievJS 22-Feb-2018
Timur Shemsedinov
 
PDF
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
it-people
 
PDF
When RV Meets CEP (RV 2016 Tutorial)
Sylvain Hallé
 
PDF
Are we ready to Go?
Adam Dudczak
 
PPTX
Java 8 Puzzlers [as presented at OSCON 2016]
Baruch Sadogursky
 
PDF
Python profiling
dreampuf
 
All I know about rsc.io/c2go
Moriyoshi Koizumi
 
Implementing Software Machines in C and Go
Eleanor McHugh
 
Introducción a Elixir
Svet Ivantchev
 
Faster Python, FOSDEM
Victor Stinner
 
Go a crash course
Eleanor McHugh
 
Python легко и просто. Красиво решаем повседневные задачи
Maxim Kulsha
 
Functional Programming inside OOP? It’s possible with Python
Carlos V.
 
Load-time Hacking using LD_PRELOAD
Dharmalingam Ganesan
 
Playing 44CON CTF for fun and profit
44CON
 
Implementing Software Machines in Go and C
Eleanor McHugh
 
Whats new in_csharp4
Abed Bukhari
 
Phil Bartie QGIS PLPython
Ross McDonald
 
Metarhia KievJS 22-Feb-2018
Timur Shemsedinov
 
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
it-people
 
When RV Meets CEP (RV 2016 Tutorial)
Sylvain Hallé
 
Are we ready to Go?
Adam Dudczak
 
Java 8 Puzzlers [as presented at OSCON 2016]
Baruch Sadogursky
 
Python profiling
dreampuf
 
Ad

Viewers also liked (6)

PDF
Bytecode Optimizations
ESUG
 
PDF
Fuse'ing python for rapid development of storage efficient FS
Chetan Giridhar
 
PPTX
Testers in product development code review phase
Chetan Giridhar
 
PDF
Design patterns in python v0.1
Chetan Giridhar
 
PPTX
PyCon India 2012: Rapid development of website search in python
Chetan Giridhar
 
PPTX
Rapid development & integration of real time communication in websites
Chetan Giridhar
 
Bytecode Optimizations
ESUG
 
Fuse'ing python for rapid development of storage efficient FS
Chetan Giridhar
 
Testers in product development code review phase
Chetan Giridhar
 
Design patterns in python v0.1
Chetan Giridhar
 
PyCon India 2012: Rapid development of website search in python
Chetan Giridhar
 
Rapid development & integration of real time communication in websites
Chetan Giridhar
 
Ad

Similar to Allison Kaptur: Bytes in the Machine: Inside the CPython interpreter, PyGotham 2014 (20)

PDF
Intro to Python
OSU Open Source Lab
 
PDF
Building Interpreters with PyPy
Daniel Neuhäuser
 
PDF
Python 2.5 reference card (2009)
gekiaruj
 
PPT
python language programming presentation
lbisht2
 
PPT
python within 50 page .ppt
sushil155005
 
PDF
An overview of Python 2.7
decoupled
 
PDF
A tour of Python
Aleksandar Veselinovic
 
PDF
Python Cheat Sheet
Muthu Vinayagam
 
PPT
Python 3000
Alexandro Colorado
 
PPTX
An Introduction : Python
Raghu Kumar
 
PDF
A Few of My Favorite (Python) Things
Michael Pirnat
 
PDF
Python introduction
Marcelo Araujo
 
PPT
Python tutorialfeb152012
Shani729
 
PPT
FALLSEM2022-23_ITA3007_ETH_VL2022230100613_Reference_Material_I_23-09-2022_py...
admin369652
 
PDF
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
it-people
 
PPT
Python Kick Start
Karthik Prakash
 
PPT
PYTHON
JOHNYAMSON
 
PPTX
Introduction to the basics of Python programming (part 3)
Pedro Rodrigues
 
PDF
Quick python reference
Jayant Parida
 
PDF
GE3151_PSPP_UNIT_5_Notes
Guru Nanak Technical Institutions
 
Intro to Python
OSU Open Source Lab
 
Building Interpreters with PyPy
Daniel Neuhäuser
 
Python 2.5 reference card (2009)
gekiaruj
 
python language programming presentation
lbisht2
 
python within 50 page .ppt
sushil155005
 
An overview of Python 2.7
decoupled
 
A tour of Python
Aleksandar Veselinovic
 
Python Cheat Sheet
Muthu Vinayagam
 
Python 3000
Alexandro Colorado
 
An Introduction : Python
Raghu Kumar
 
A Few of My Favorite (Python) Things
Michael Pirnat
 
Python introduction
Marcelo Araujo
 
Python tutorialfeb152012
Shani729
 
FALLSEM2022-23_ITA3007_ETH_VL2022230100613_Reference_Material_I_23-09-2022_py...
admin369652
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
it-people
 
Python Kick Start
Karthik Prakash
 
PYTHON
JOHNYAMSON
 
Introduction to the basics of Python programming (part 3)
Pedro Rodrigues
 
Quick python reference
Jayant Parida
 
GE3151_PSPP_UNIT_5_Notes
Guru Nanak Technical Institutions
 

Recently uploaded (20)

PPT
1. SYSTEMS, ROLES, AND DEVELOPMENT METHODOLOGIES.ppt
zilow058
 
PDF
2010_Book_EnvironmentalBioengineering (1).pdf
EmilianoRodriguezTll
 
PPTX
Chapter_Seven_Construction_Reliability_Elective_III_Msc CM
SubashKumarBhattarai
 
PDF
AI-Driven IoT-Enabled UAV Inspection Framework for Predictive Maintenance and...
ijcncjournal019
 
PPTX
quantum computing transition from classical mechanics.pptx
gvlbcy
 
PPTX
Civil Engineering Practices_BY Sh.JP Mishra 23.09.pptx
bineetmishra1990
 
PPTX
Module2 Data Base Design- ER and NF.pptx
gomathisankariv2
 
PPTX
MT Chapter 1.pptx- Magnetic particle testing
ABCAnyBodyCanRelax
 
PDF
Introduction to Ship Engine Room Systems.pdf
Mahmoud Moghtaderi
 
PPTX
Information Retrieval and Extraction - Module 7
premSankar19
 
PDF
LEAP-1B presedntation xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
hatem173148
 
PPTX
22PCOAM21 Session 2 Understanding Data Source.pptx
Guru Nanak Technical Institutions
 
PPTX
Tunnel Ventilation System in Kanpur Metro
220105053
 
PPTX
MULTI LEVEL DATA TRACKING USING COOJA.pptx
dollysharma12ab
 
PDF
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
PPTX
Inventory management chapter in automation and robotics.
atisht0104
 
PPTX
database slide on modern techniques for optimizing database queries.pptx
aky52024
 
PDF
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
PDF
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
PPTX
Victory Precisions_Supplier Profile.pptx
victoryprecisions199
 
1. SYSTEMS, ROLES, AND DEVELOPMENT METHODOLOGIES.ppt
zilow058
 
2010_Book_EnvironmentalBioengineering (1).pdf
EmilianoRodriguezTll
 
Chapter_Seven_Construction_Reliability_Elective_III_Msc CM
SubashKumarBhattarai
 
AI-Driven IoT-Enabled UAV Inspection Framework for Predictive Maintenance and...
ijcncjournal019
 
quantum computing transition from classical mechanics.pptx
gvlbcy
 
Civil Engineering Practices_BY Sh.JP Mishra 23.09.pptx
bineetmishra1990
 
Module2 Data Base Design- ER and NF.pptx
gomathisankariv2
 
MT Chapter 1.pptx- Magnetic particle testing
ABCAnyBodyCanRelax
 
Introduction to Ship Engine Room Systems.pdf
Mahmoud Moghtaderi
 
Information Retrieval and Extraction - Module 7
premSankar19
 
LEAP-1B presedntation xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
hatem173148
 
22PCOAM21 Session 2 Understanding Data Source.pptx
Guru Nanak Technical Institutions
 
Tunnel Ventilation System in Kanpur Metro
220105053
 
MULTI LEVEL DATA TRACKING USING COOJA.pptx
dollysharma12ab
 
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
Inventory management chapter in automation and robotics.
atisht0104
 
database slide on modern techniques for optimizing database queries.pptx
aky52024
 
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
Victory Precisions_Supplier Profile.pptx
victoryprecisions199
 

Allison Kaptur: Bytes in the Machine: Inside the CPython interpreter, PyGotham 2014

  • 1. Byterun: A (C)Python interpreter in Python Allison Kaptur ! github.com/akaptur akaptur.github.io @akaptur
  • 2. Byterun with Ned Batchelder ! Based on # pyvm2 by Paul Swartz (z3p) from http://www.twistedmatrix.com/users/z3p/
  • 3. Why would you do such a thing >>> if a or b: ... do_stuff()
  • 4. Some things we can do out = "" for i in range(5): out = out + str(i) print(out)
  • 5. Some things we can do def fn(a, b=17, c="Hello", d=[]): d.append(99) print(a, b, c, d) ! fn(1) fn(2, 3) fn(3, c="Bye") fn(4, d=["What?"]) fn(5, "b", "c")
  • 6. Some things we can do def verbose(func): def _wrapper(*args, **kwargs): return func(*args, **kwargs) return _wrapper ! @verbose def add(x, y): return x+y ! add(7, 3)
  • 7. Some things we can do try: raise ValueError("oops") except ValueError as e: print("Caught: %s" % e) print("All done")
  • 8. Some things we can do class NullContext(object): def __enter__(self): l.append('i') return self ! def __exit__(self, exc_type, exc_val, exc_tb): l.append('o') return False ! l = [] for i in range(3): with NullContext(): l.append('w') if i % 2: break l.append('z') l.append('e') ! l.append('r') s = ''.join(l) print("Look: %r" % s) assert s == "iwzoeiwor"
  • 9. Some things we can do g = (x*x for x in range(3)) print(list(g))
  • 10. A problem g = (x*x for x in range(5)) h = (y+1 for y in g) print(list(h))
  • 11. The Python virtual machine: ! A bytecode interpreter
  • 12. Bytecode: the internal representation of a python program in the interpreter
  • 13. Bytecode: it’s bytes! >>> def mod(a, b): ... ans = a % b ... return ans
  • 14. Bytecode: it’s bytes! >>> def mod(a, b): ... ans = a % b ... return ans >>> mod.func_code.co_code Function Code object Bytecode
  • 15. Bytecode: it’s bytes! >>> def mod(a, b): ... ans = a % b ... return ans >>> mod.func_code.co_code '|x00x00|x01x00x16}x02x00|x02x00S'
  • 16. Bytecode: it’s bytes! >>> def mod(a, b): ... ans = a % b ... return ans >>> mod.func_code.co_code ‘|x00x00|x01x00x16}x02x00|x02x00S' >>> [ord(b) for b in mod.func_code.co_code] [124, 0, 0, 124, 1, 0, 22, 125, 2, 0, 124, 2, 0, 83]
  • 17. dis, a bytecode disassembler >>> import dis >>> dis.dis(mod) 2 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b) 6 BINARY_MODULO 7 STORE_FAST 2 (ans) ! 3 10 LOAD_FAST 2 (ans) 13 RETURN_VALUE
  • 18. dis, a bytecode disassembler >>> import dis >>> dis.dis(mod) 2 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b) 6 BINARY_MODULO 7 STORE_FAST 2 (ans) ! 3 10 LOAD_FAST 2 (ans) 13 RETURN_VALUE Line Number Index in bytecode Instruction name, for humans More bytes, the argument to each instruction Hint about arguments
  • 19. whatever some other thing something whatever some other thing something a b whatever some other thing something ans Before After BINARY_MODULO After LOAD_FAST Data stack on a frame
  • 20. def foo(): x = 1 def bar(y): z = y + 2 return z return bar(x) foo() # <--- (1) ! c a l l ! s t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [<foo>] k ---------------------
  • 21. def foo(): x = 1 def bar(y): z = y + 2 return z return bar(x) # <--- (2) foo() # <--- (1) ! c a l l --------------------- | foo Frame | -> blocks: [] s | | -> data: [<bar>, 1] t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [] k ---------------------
  • 22. def foo(): x = 1 def bar(y): z = y + 2 # <--- (3) return z return bar(x) # <--- (2) foo() # <--- (1) ! c --------------------- a | bar Frame | -> blocks: [] l | (newest) | -> data: [1, 2] l --------------------- | foo Frame | -> blocks: [] s | | -> data: [] t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [] k ---------------------
  • 23. def foo(): x = 1 def bar(y): z = y + 2 # <--- (3) return z return bar(x) # <--- (2) foo() # <--- (1) ! c --------------------- a | bar Frame | -> blocks: [] l | (newest) | -> data: [3] l --------------------- | foo Frame | -> blocks: [] s | | -> data: [] t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [] k ---------------------
  • 24. def foo(): x = 1 def bar(y): z = y + 2 # <--- (3) return z return bar(x) # <--- (2) foo() # <--- (1) ! c a l l --------------------- | foo Frame | -> blocks: [] s | | -> data: [3] t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [] k ---------------------
  • 25. def foo(): x = 1 def bar(y): z = y + 2 # <--- (3) return z return bar(x) # <--- (2) foo() # <--- (1) ! c a l l ! s t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [3] k ---------------------
  • 26. dis, a bytecode disassembler >>> import dis >>> dis.dis(mod) 2 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b) 6 BINARY_MODULO 7 STORE_FAST 2 (ans) ! 3 10 LOAD_FAST 2 (ans) 13 RETURN_VALUE
  • 28. } /*switch*/ /* Main switch on opcode */ READ_TIMESTAMP(inst0); ! switch (opcode) {
  • 29. #ifdef CASE_TOO_BIG default: switch (opcode) { #endif /* Turn this on if your compiler chokes on the big switch: */ /* #define CASE_TOO_BIG 1 */
  • 30. Back to that bytecode ! >>> dis.dis(mod) 2 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b) 6 BINARY_MODULO 7 STORE_FAST 2 (ans) ! 3 10 LOAD_FAST 2 (ans) 13 RETURN_VALUE
  • 31. case LOAD_FAST: x = GETLOCAL(oparg); if (x != NULL) { Py_INCREF(x); PUSH(x); goto fast_next_opcode; } format_exc_check_arg(PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(co->co_varnames, oparg)); break;
  • 32. case BINARY_MODULO: w = POP(); v = TOP(); if (PyString_CheckExact(v)) x = PyString_Format(v, w); else x = PyNumber_Remainder(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); if (x != NULL) continue; break;
  • 33. It’s “dynamic” >>> def mod(a, b): ... ans = a % b ... return ans >>> mod(15, 4) 3
  • 34. “Dynamic” >>> def mod(a, b): ... ans = a % b ... return ans >>> mod(15, 4) 3 >>> mod(“%s%s”, (“Py”, “Gotham”))
  • 35. “Dynamic” >>> def mod(a, b): ... ans = a % b ... return ans >>> mod(15, 4) 3 >>> mod(“%s%s”, (“Py”, “Gotham”)) PyGotham
  • 36. “Dynamic” >>> def mod(a, b): ... ans = a % b ... return ans >>> mod(15, 4) 3 >>> mod(“%s%s”, (“Py”, “Gotham”)) PyGotham >>> print “%s%s” % (“Py”, “Gotham”) PyGotham
  • 37. case BINARY_MODULO: w = POP(); v = TOP(); if (PyString_CheckExact(v)) x = PyString_Format(v, w); else x = PyNumber_Remainder(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); if (x != NULL) continue; break;
  • 38. >>> class Surprising(object): … def __mod__(self, other): … print “Surprise!” ! >>> s = Surprising() >>> t = Surprsing() >>> s % t Surprise!
  • 39. “In the general absence of type information, almost every instruction must be treated as INVOKE_ARBITRARY_METHOD.” ! - Russell Power and Alex Rubinsteyn, “How Fast Can We Make Interpreted Python?”
  • 40. Back to our problem g = (x*x for x in range(5)) h = (y+1 for y in g) print(list(h))
  • 41. def foo(): x = 1 def bar(y): z = y + 2 return z return bar(x) foo() # <--- (1) ! c a l l ! s t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [<foo>] k ---------------------
  • 42. def foo(): x = 1 def bar(y): z = y + 2 return z return bar(x) # <--- (2) foo() # <--- (1) ! c a l l --------------------- | foo Frame | -> blocks: [] s | | -> data: [<bar>, 1] t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [] k ---------------------
  • 43. def foo(): x = 1 def bar(y): z = y + 2 # <--- (3) return z return bar(x) # <--- (2) foo() # <--- (1) ! c --------------------- a | bar Frame | -> blocks: [] l | (newest) | -> data: [1, 2] l --------------------- | foo Frame | -> blocks: [] s | | -> data: [] t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [] k ---------------------
  • 44. def foo(): x = 1 def bar(y): z = y + 2 # <--- (3) return z return bar(x) # <--- (2) foo() # <--- (1) ! c --------------------- a | bar Frame | -> blocks: [] l | (newest) | -> data: [3] l --------------------- | foo Frame | -> blocks: [] s | | -> data: [] t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [] k ---------------------
  • 45. def foo(): x = 1 def bar(y): z = y + 2 # <--- (3) return z return bar(x) # <--- (2) foo() # <--- (1) ! c a l l --------------------- | foo Frame | -> blocks: [] s | | -> data: [3] t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [] k ---------------------
  • 46. def foo(): x = 1 def bar(y): z = y + 2 # <--- (3) return z return bar(x) # <--- (2) foo() # <--- (1) ! c a l l ! s t --------------------- a | main (module) Frame | -> blocks: [] c | (oldest) | -> data: [3] k ---------------------
  • 47. Back to our problem g = (x*x for x in range(5)) h = (y+1 for y in g) print(list(h))
  • 48. More Great blogs http://tech.blog.aknin.name/category/my-projects/ pythons-innards/ by @aknin http://eli.thegreenplace.net/ by Eli Bendersky ! Contribute! Find bugs! https://github.com/nedbat/byterun ! Apply to Hacker School! www.hackerschool.com/apply