SlideShare ist ein Scribd-Unternehmen logo
1 von 49
Downloaden Sie, um offline zu lesen
Async I/O in Python
We're here to talk about asynchronous I/O in Python
Widely accepted as a weakness of Python
People are working on fixing this in 3.4
Extremely broad, nuanced topic
I expect there's a huge range in people's level of understanding here
People often talk past each other, debating obscure points
The goal here is to learn more about the topic, not debate I/O strategies
Waiting
You're doing some I/O
It can't complete immediately (e.g. waiting for server to respond)
What do you do now?
If there's anything else useful to be done, surely do that
Async Strategies
Multiple processes
Multiple threads
Single thread, non-blocking I/O
A combination of all three might make sense
We're here to talk about frameworks for the latter
Non-blocking I/O
Usually, if an I/O operation (read/write/etc.) can't complete, you block
Blocking means that the kernel puts you too sleep
If you're sleeping, you don't have the opportunity to do other useful work
Instead, use non-blocking I/O operations
Kernel returns immediately if it can't complete the I/O
You end up with a bunch of in-progress I/O operations
You use select() to have the kernel tell you when one of them can progress
01
02
03 import socket
04
05 sock = socket.socket()
06 sock.connect(('localhost', 1234))
07
08
09 sock.send('foon' * 10 * 1024 * 1024)
10
11
12
13
14
15
16
17
18
19
20
21
Simple example, connect to a server on port 1234, write a bunch of stuff
This send() function won't finish until all the data is written
While you're waiting for the I/O to complete, you can't do anything else
If you're not familiar with berkley sockets ...
socket() creates a socket ... it's just a data structure
connect() initiates the TCP connection with the server
Some handshake packets will go back and forth before this completes
send() takes the data buffer, splits up and sends as TCP packets
01
02
03 import socket
04
05 sock = socket.socket()
06 sock.connect(('localhost', 1234))
07 sock.setblocking(0)
08
09 sock.send('foon' * 10 * 1024 * 1024)
10
11
12
13
14
15
16
17
18
19
20
21
01
02
03 import socket
04
05 sock = socket.socket()
06 sock.connect(('localhost', 1234))
07 sock.setblocking(0)
08
09 buf = buffer('foon' * 10 * 1024 * 1024)
10 while len(buf):
11 buf = buf[sock.send(buf):]
12
13
14
15
16
17
18
19
20
21
01 import errno
02 import select
03 import socket
04
05 sock = socket.socket()
06 sock.connect(('localhost', 1234))
07 sock.setblocking(0)
08
09 buf = buffer('foon' * 10 * 1024 * 1024)
10 while len(buf):
11 try:
12 buf = buf[sock.send(buf):]
13 except socket.error, e:
14 if e.errno != errno.EAGAIN:
15 raise e
16
17
18
19
20
21
01 import errno
02 import select
03 import socket
04
05 sock = socket.socket()
06 sock.connect(('localhost', 1234))
07 sock.setblocking(0)
08
09 buf = buffer('foon' * 10 * 1024 * 1024)
10 while len(buf):
11 try:
12 buf = buf[sock.send(buf):]
13 except socket.error, e:
14 if e.errno != errno.EAGAIN:
15 raise e
16
17
18
19
20
21 select.select([], [sock], [])
01 import errno
02 import select
03 import socket
04
05 sock = socket.socket()
06 sock.connect(('localhost', 1234))
07 sock.setblocking(0)
08
09 buf = buffer('foon' * 10 * 1024 * 1024)
10 while len(buf):
11 try:
12 buf = buf[sock.send(buf):]
13 except socket.error, e:
14 if e.errno != errno.EAGAIN:
15 raise e
16
17 i = 0
18 while i < 5000000:
19 i += 1
20
21 select.select([], [sock], [])
Eventlet
Eventlet is one of several async I/O frameworks for Python
It's magic, to its detriment IMHO
Co-operative co-routine scheduling
Eventlet coroutines are called green threads (from Java)
green threads != threads
Many greenthreads in one OS thread
They are very cheap
We call them coroutines because they cooperatively yield to one another
greenlet allows you to save a stack and switch to another stack
01
02 from eventlet.green import socket
03
04
05
06
07
08
09
10
11
12
13 sock = socket.socket()
14 sock.connect(('localhost', 1234))
15 sock.send('foon' * 10 * 1024 * 1024)
16
17
18
19
20
21
01 import eventlet
02 from eventlet.green import socket
03
04 def busy_loop():
05 pass
06
07
08
09
10
11 eventlet.spawn(busy_loop)
12
13 sock = socket.socket()
14 sock.connect(('localhost', 1234))
15 sock.send('foon' * 10 * 1024 * 1024)
16
17
18
19
20
21
01 import eventlet
02 from eventlet.green import socket
03
04 def busy_loop():
05 while True:
06 i = 0
07 while i < 5000000:
08 i += 1
09
10
11 eventlet.spawn(busy_loop)
12
13 sock = socket.socket()
14 sock.connect(('localhost', 1234))
15 sock.send('foon' * 10 * 1024 * 1024)
16
17
18
19
20
21
01 import eventlet
02 from eventlet.green import socket
03
04 def busy_loop():
05 while True:
06 i = 0
07 while i < 5000000:
08 i += 1
09 eventlet.sleep()
10
11 eventlet.spawn(busy_loop)
12
13 sock = socket.socket()
14 sock.connect(('localhost', 1234))
15 sock.send('foon' * 10 * 1024 * 1024)
16
17
18
19
20
21
Twisted
Eventlet has a scheduler, twisted has an event loop
Event loop is a loop (i.e. while loop) which checks for I/O events
Twisted invokes callbacks for events, rather than scheduling coroutines
Eventlet is confusing because magic
Twisted is confusing because abstractions
01
02 from twisted.internet import reactor
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21 reactor.run()
01 from twisted.internet import protocol
02 from twisted.internet import reactor
03
04
05
06
07
08
09
10
11
12 reactor.connectTCP('localhost', 1234,
13 protocol.ClientFactory())
14
15
16
17
18
19
20
21 reactor.run()
01 from twisted.internet import protocol
02 from twisted.internet import reactor
03
04 class Test(protocol.Protocol):
05 pass
06
07
08 class TestFactory(protocol.ClientFactory):
09 def buildProtocol(self, addr):
10 return Test()
11
12 reactor.connectTCP('localhost', 1234, TestFactory())
13
14
15
16
17
18
19
20
21 reactor.run()
01 from twisted.internet import protocol
02 from twisted.internet import reactor
03
04 class Test(protocol.Protocol):
05 def connectionMade(self):
06 self.transport.write('foon' * 2 * 1024 * 1024)
07
08 class TestFactory(protocol.ClientFactory):
09 def buildProtocol(self, addr):
10 return Test()
11
12 reactor.connectTCP('localhost', 1234, TestFactory())
13
14
15
16
17
18
19
20
21 reactor.run()
01 from twisted.internet import protocol
02 from twisted.internet import reactor
03
04 class Test(protocol.Protocol):
05 def connectionMade(self):
06 self.transport.write('foon' * 2 * 1024 * 1024)
07
08 class TestFactory(protocol.ClientFactory):
09 def buildProtocol(self, addr):
10 return Test()
11
12 reactor.connectTCP('localhost', 1234, TestFactory())
13
14 def busy_loop():
15 i = 0
16 while i < 5000000:
17 i += 1
18
19 reactor.callLater(0, busy_loop)
20
21 reactor.run()
01 from twisted.internet import protocol
02 from twisted.internet import reactor
03
04 class Test(protocol.Protocol):
05 def connectionMade(self):
06 self.transport.write('foon' * 2 * 1024 * 1024)
07
08 class TestFactory(protocol.ClientFactory):
09 def buildProtocol(self, addr):
10 return Test()
11
12 reactor.connectTCP('localhost', 1234, TestFactory())
13
14 def busy_loop():
15 i = 0
16 while i < 5000000:
17 i += 1
18 reactor.callLater(0, busy_loop)
19 reactor.callLater(0, busy_loop)
20
21 reactor.run()
Tulip
Guido's "Async I/O Support Rebooted"
Support for both coroutine and callback models
It's event loop is called an event loop
01
02
03
04 import tulip
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 event_loop = tulip.get_event_loop()
28
39
30 event_loop.run_forever()
01
02 import socket
03
04 import tulip
05
06 sock = socket.socket()
07 sock.connect(('localhost', 1234))
08 sock.setblocking(0)
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 event_loop = tulip.get_event_loop()
28
39
30 event_loop.run_forever()
01 import errno
02 import socket
03
04 import tulip
05
06 sock = socket.socket()
07 sock.connect(('localhost', 1234))
08 sock.setblocking(0)
09
10 buf = memoryview(str.encode('foon' * 2 * 1024 * 1024))
11 def do_write():
12 global buf
13 while True:
14 try:
15 buf = buf[sock.send(buf):]
16 except socket.error as e:
17 if e.errno != errno.EAGAIN:
18 raise e
19 return
20
21
22
23
24
25
26
27 event_loop = tulip.get_event_loop()
28 event_loop.add_writer(sock, do_write)
39
30 event_loop.run_forever()
01 import errno
02 import socket
03
04 import tulip
05
06 sock = socket.socket()
07 sock.connect(('localhost', 1234))
08 sock.setblocking(0)
09
10 buf = memoryview(str.encode('foon' * 2 * 1024 * 1024))
11 def do_write():
12 global buf
13 while True:
14 try:
15 buf = buf[sock.send(buf):]
16 except socket.error as e:
17 if e.errno != errno.EAGAIN:
18 raise e
19 return
20
21 def busy_loop():
22 i = 0
23 while i < 5000000:
24 i += 1
25 event_loop.call_soon(busy_loop)
26
27 event_loop = tulip.get_event_loop()
28 event_loop.add_writer(sock, do_write)
39 event_loop.call_soon(busy_loop)
30 event_loop.run_forever()
01 import tulip
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21 event_loop = tulip.get_event_loop()
22
23 event_loop.run_forever()
01 import tulip
02
03 class Protocol(tulip.Protocol):
04
05 buf = b'foon' * 10 * 1024 * 1024
06
07 def connection_made(self, transport):
08
09 transport.write(self.buf)
10 transport.close()
11
12
13
14
15
16
17
18
19
20
21 event_loop = tulip.get_event_loop()
22
23 event_loop.run_forever()
01 import tulip
02
03 class Protocol(tulip.Protocol):
04
05 buf = b'foon' * 10 * 1024 * 1024
06
07 def connection_made(self, transport):
08
09 transport.write(self.buf)
10 transport.close()
11
12
13
14
15
16
17
18
19
20
21 event_loop = tulip.get_event_loop()
22 tulip.Task(event_loop.create_connection(Protocol, 'localhost', 1234))
23 event_loop.run_forever()
01 import tulip
02
03 class Protocol(tulip.Protocol):
04
05 buf = b'foon' * 10 * 1024 * 1024
06
07 def connection_made(self, transport):
08
09 transport.write(self.buf)
10 transport.close()
11
12 def connection_lost(self, exc):
13 event_loop.stop()
14
15
16
17
18
19
20
21 event_loop = tulip.get_event_loop()
22 tulip.Task(event_loop.create_connection(Protocol, 'localhost', 1234))
23 event_loop.run_forever()
01 import tulip
02
03 class Protocol(tulip.Protocol):
04
05 buf = b'foon' * 10 * 1024 * 1024
06
07 def connection_made(self, transport):
08 event_loop.call_soon(busy_loop)
09 transport.write(self.buf)
10 transport.close()
11
12 def connection_lost(self, exc):
13 event_loop.stop()
14
15 def busy_loop():
16 i = 0
17 while i < 5000000:
18 i += 1
19 event_loop.call_soon(busy_loop)
20
21 event_loop = tulip.get_event_loop()
22 tulip.Task(event_loop.create_connection(Protocol, 'localhost', 1234))
23 event_loop.run_forever()
Generators as Coroutines
01 import os
02
03 def contents_of_files(dir):
04 ret = []
05 for f in os.listdir(dir):
06 path = os.path.join(dir, f)
07 ret.append((path, file(path).read()))
08 return ret
09
10 for path, contents in contents_of_files(dir):
11 if search_for in contents:
12 print("found", search_for, "in", path)
13 break
01 import os
02
03 def contents_of_files(dir):
04
05 for f in os.listdir(dir):
06 path = os.path.join(dir, f)
07 yield (path, file(path).read())
08
09
10 for path, contents in contents_of_files(dir):
11 if search_for in contents:
12 print("found", search_for, "in", path)
13 break
01 def gen():
02 i = 0
03 while i < 2:
04 print(i)
05 yield
06 i += 1
07
08 i = gen()
09 print("yo!")
10 next(i)
11 print("hello!")
12 next(i)
13 print("bye!")
14 try:
15 next(i)
16 except StopIteration:
17 print("stopped")
01 Task = collections.namedtuple('Task', ['generator', 'wfd', 'idle'])
02
03 running = True
04
05 def quit():
06 global running
07 running = False
08
09 while running:
10 finished = []
11 for n, t in enumerate(tasks):
12 try:
13 next(t.generator)
14 except StopIteration:
15 finished.append(n)
16 map(tasks.pop, finished)
17
18 wfds = [t.wfd for t in tasks if t.wfd]
19 timeout = 0 if [t for t in tasks if t.idle] else None
20
21 select.select([], wfds, [], timeout)
01 def busy_loop():
02 while True:
03 i = 0
04 while i < 5000000:
05 i += 1
06 yield
07
08 tasks.append(Task(busy_loop(), wfd=None, idle=True))
09
10
11
12
13
14
15
16
17
18
19
20
21
01 sock = socket.socket()
02 sock.connect(('localhost', 1234))
03 sock.setblocking(0)
04
05 def write(data):
06 buf = memoryview(data)
07 while len(buf):
08 try:
09 buf = buf[sock.send(buf):]
10 except socket.error as e:
11 if e.errno != errno.EAGAIN:
12 raise e
13 yield
14
15 def write_stuff():
16 yield from write(b'foon' * 2 * 1024 * 1024)
17 yield from write(b'barn' * 2 * 1024 * 1024)
18 quit()
19
20 tasks.append(Task(write_stuff(), wfd=sock, idle=False))
21
References
• My blog - http://blogs.gnome.org/markmc/2013/06/04/async-io-and-python
• Eventlet - http://eventlet.net
• Twisted - http://twistedmatrix.com
• Tulip - http://www.python.org/dev/peps/pep-3156
• yield from - http://www.python.org/dev/peps/pep-0380

Weitere ähnliche Inhalte

Was ist angesagt?

Profiling of Oracle Function Calls
Profiling of Oracle Function CallsProfiling of Oracle Function Calls
Profiling of Oracle Function Calls
Enkitec
 
How to recover malare assembly codes
How to recover malare assembly codesHow to recover malare assembly codes
How to recover malare assembly codes
FACE
 

Was ist angesagt? (20)

Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?
 
Profiling of Oracle Function Calls
Profiling of Oracle Function CallsProfiling of Oracle Function Calls
Profiling of Oracle Function Calls
 
Use C++ to Manipulate mozSettings in Gecko
Use C++ to Manipulate mozSettings in GeckoUse C++ to Manipulate mozSettings in Gecko
Use C++ to Manipulate mozSettings in Gecko
 
Programação assíncrona utilizando Coroutines
Programação assíncrona utilizando CoroutinesProgramação assíncrona utilizando Coroutines
Programação assíncrona utilizando Coroutines
 
Promise is a Promise
Promise is a PromisePromise is a Promise
Promise is a Promise
 
How to recover malare assembly codes
How to recover malare assembly codesHow to recover malare assembly codes
How to recover malare assembly codes
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.
 
Extreme JavaScript Performance
Extreme JavaScript PerformanceExtreme JavaScript Performance
Extreme JavaScript Performance
 
Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)
 
Ch4
Ch4Ch4
Ch4
 
Play image
Play imagePlay image
Play image
 
Goroutines and Channels in practice
Goroutines and Channels in practiceGoroutines and Channels in practice
Goroutines and Channels in practice
 
The Ring programming language version 1.4 book - Part 21 of 30
The Ring programming language version 1.4 book - Part 21 of 30The Ring programming language version 1.4 book - Part 21 of 30
The Ring programming language version 1.4 book - Part 21 of 30
 
2 презентация rx java+android
2 презентация rx java+android2 презентация rx java+android
2 презентация rx java+android
 
Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가
 
The Ring programming language version 1.5.4 book - Part 25 of 185
The Ring programming language version 1.5.4 book - Part 25 of 185The Ring programming language version 1.5.4 book - Part 25 of 185
The Ring programming language version 1.5.4 book - Part 25 of 185
 
The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184
 
Concurrency in Golang
Concurrency in GolangConcurrency in Golang
Concurrency in Golang
 
Programming Sideways: Asynchronous Techniques for Android
Programming Sideways: Asynchronous Techniques for AndroidProgramming Sideways: Asynchronous Techniques for Android
Programming Sideways: Asynchronous Techniques for Android
 
The Ring programming language version 1.3 book - Part 17 of 88
The Ring programming language version 1.3 book - Part 17 of 88The Ring programming language version 1.3 book - Part 17 of 88
The Ring programming language version 1.3 book - Part 17 of 88
 

Andere mochten auch

Andere mochten auch (6)

Python Ireland - Who, how, what
Python Ireland - Who, how, whatPython Ireland - Who, how, what
Python Ireland - Who, how, what
 
Python for PHP developers
Python for PHP developersPython for PHP developers
Python for PHP developers
 
Pycon 2016
Pycon 2016Pycon 2016
Pycon 2016
 
Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati
Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati
Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati
 
Python idioms
Python idiomsPython idioms
Python idioms
 
Object Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in PythonObject Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in Python
 

Ähnlich wie Async I/O in Python

Orsiso
OrsisoOrsiso
Orsiso
e27
 
C++11 concurrency
C++11 concurrencyC++11 concurrency
C++11 concurrency
xu liwei
 

Ähnlich wie Async I/O in Python (20)

Introduction to asyncio
Introduction to asyncioIntroduction to asyncio
Introduction to asyncio
 
Kotlin - Coroutine
Kotlin - CoroutineKotlin - Coroutine
Kotlin - Coroutine
 
A deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio moduleA deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio module
 
Udp socket programming(Florian)
Udp socket programming(Florian)Udp socket programming(Florian)
Udp socket programming(Florian)
 
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando CoroutinesTDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
 
Lab
LabLab
Lab
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
 
Parallel Processing
Parallel ProcessingParallel Processing
Parallel Processing
 
C10k and beyond - Uri Shamay, Akamai
C10k and beyond - Uri Shamay, AkamaiC10k and beyond - Uri Shamay, Akamai
C10k and beyond - Uri Shamay, Akamai
 
NHibernate Configuration Patterns
NHibernate Configuration PatternsNHibernate Configuration Patterns
NHibernate Configuration Patterns
 
Orsiso
OrsisoOrsiso
Orsiso
 
BUILDING APPS WITH ASYNCIO
BUILDING APPS WITH ASYNCIOBUILDING APPS WITH ASYNCIO
BUILDING APPS WITH ASYNCIO
 
Writing Server in Python
Writing Server in PythonWriting Server in Python
Writing Server in Python
 
droidcon Transylvania - Kotlin Coroutines
droidcon Transylvania - Kotlin Coroutinesdroidcon Transylvania - Kotlin Coroutines
droidcon Transylvania - Kotlin Coroutines
 
C++11 concurrency
C++11 concurrencyC++11 concurrency
C++11 concurrency
 
Networking Core Concept
Networking Core ConceptNetworking Core Concept
Networking Core Concept
 
The journey of asyncio adoption in instagram
The journey of asyncio adoption in instagramThe journey of asyncio adoption in instagram
The journey of asyncio adoption in instagram
 
Python Coroutines, Present and Future
Python Coroutines, Present and FuturePython Coroutines, Present and Future
Python Coroutines, Present and Future
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
sockets_intro.ppt
sockets_intro.pptsockets_intro.ppt
sockets_intro.ppt
 

Mehr von Python Ireland

Web-service based Mobile Geospatial Application Development using Python
Web-service based Mobile Geospatial Application Development using PythonWeb-service based Mobile Geospatial Application Development using Python
Web-service based Mobile Geospatial Application Development using Python
Python Ireland
 
Python Ireland Nov 2009 Talk - Appengine
Python Ireland Nov 2009 Talk - AppenginePython Ireland Nov 2009 Talk - Appengine
Python Ireland Nov 2009 Talk - Appengine
Python Ireland
 

Mehr von Python Ireland (18)

What's the Scoop with Python 3?
What's the Scoop with Python 3?What's the Scoop with Python 3?
What's the Scoop with Python 3?
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)
 
Introduction to Erlang for Python Programmers
Introduction to Erlang for Python ProgrammersIntroduction to Erlang for Python Programmers
Introduction to Erlang for Python Programmers
 
Web-service based Mobile Geospatial Application Development using Python
Web-service based Mobile Geospatial Application Development using PythonWeb-service based Mobile Geospatial Application Development using Python
Web-service based Mobile Geospatial Application Development using Python
 
Utopia Kingdoms scaling case. From 4 users to 50.000+
Utopia Kingdoms scaling case. From 4 users to 50.000+Utopia Kingdoms scaling case. From 4 users to 50.000+
Utopia Kingdoms scaling case. From 4 users to 50.000+
 
The Larch - a visual interactive programming environment
The Larch - a visual interactive programming environmentThe Larch - a visual interactive programming environment
The Larch - a visual interactive programming environment
 
Python vs JLizard.... a python logging experience
Python vs JLizard.... a python logging experiencePython vs JLizard.... a python logging experience
Python vs JLizard.... a python logging experience
 
Vim and Python
Vim and PythonVim and Python
Vim and Python
 
Python Ireland Nov 2009 Talk - Appengine
Python Ireland Nov 2009 Talk - AppenginePython Ireland Nov 2009 Talk - Appengine
Python Ireland Nov 2009 Talk - Appengine
 
Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...
Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...
Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...
 
Python Ireland Nov 2010 Talk: Unit Testing
Python Ireland Nov 2010 Talk: Unit TestingPython Ireland Nov 2010 Talk: Unit Testing
Python Ireland Nov 2010 Talk: Unit Testing
 
Python Ireland Nov 2010 - RESTing with Django
Python Ireland Nov 2010 - RESTing with DjangoPython Ireland Nov 2010 - RESTing with Django
Python Ireland Nov 2010 - RESTing with Django
 
Python Ireland Feb '11 Talks: Introduction to Python
Python Ireland Feb '11 Talks: Introduction to PythonPython Ireland Feb '11 Talks: Introduction to Python
Python Ireland Feb '11 Talks: Introduction to Python
 
Python Ireland Dec Talks - Windows Azure -- The Nuts and Bolts
Python Ireland Dec Talks - Windows Azure -- The Nuts and BoltsPython Ireland Dec Talks - Windows Azure -- The Nuts and Bolts
Python Ireland Dec Talks - Windows Azure -- The Nuts and Bolts
 
Lambada
LambadaLambada
Lambada
 
Python for cloud computing
Python for cloud computingPython for cloud computing
Python for cloud computing
 
IPython: The awesome python shell
IPython: The awesome python shellIPython: The awesome python shell
IPython: The awesome python shell
 
[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan
[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan
[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan
 

Kürzlich hochgeladen

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 

Kürzlich hochgeladen (20)

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 

Async I/O in Python

  • 1.
  • 2. Async I/O in Python
  • 3. We're here to talk about asynchronous I/O in Python Widely accepted as a weakness of Python People are working on fixing this in 3.4 Extremely broad, nuanced topic I expect there's a huge range in people's level of understanding here People often talk past each other, debating obscure points The goal here is to learn more about the topic, not debate I/O strategies
  • 5. You're doing some I/O It can't complete immediately (e.g. waiting for server to respond) What do you do now? If there's anything else useful to be done, surely do that
  • 7. Multiple processes Multiple threads Single thread, non-blocking I/O A combination of all three might make sense We're here to talk about frameworks for the latter
  • 9. Usually, if an I/O operation (read/write/etc.) can't complete, you block Blocking means that the kernel puts you too sleep If you're sleeping, you don't have the opportunity to do other useful work Instead, use non-blocking I/O operations Kernel returns immediately if it can't complete the I/O You end up with a bunch of in-progress I/O operations You use select() to have the kernel tell you when one of them can progress
  • 10. 01 02 03 import socket 04 05 sock = socket.socket() 06 sock.connect(('localhost', 1234)) 07 08 09 sock.send('foon' * 10 * 1024 * 1024) 10 11 12 13 14 15 16 17 18 19 20 21
  • 11. Simple example, connect to a server on port 1234, write a bunch of stuff This send() function won't finish until all the data is written While you're waiting for the I/O to complete, you can't do anything else If you're not familiar with berkley sockets ... socket() creates a socket ... it's just a data structure connect() initiates the TCP connection with the server Some handshake packets will go back and forth before this completes send() takes the data buffer, splits up and sends as TCP packets
  • 12. 01 02 03 import socket 04 05 sock = socket.socket() 06 sock.connect(('localhost', 1234)) 07 sock.setblocking(0) 08 09 sock.send('foon' * 10 * 1024 * 1024) 10 11 12 13 14 15 16 17 18 19 20 21
  • 13. 01 02 03 import socket 04 05 sock = socket.socket() 06 sock.connect(('localhost', 1234)) 07 sock.setblocking(0) 08 09 buf = buffer('foon' * 10 * 1024 * 1024) 10 while len(buf): 11 buf = buf[sock.send(buf):] 12 13 14 15 16 17 18 19 20 21
  • 14. 01 import errno 02 import select 03 import socket 04 05 sock = socket.socket() 06 sock.connect(('localhost', 1234)) 07 sock.setblocking(0) 08 09 buf = buffer('foon' * 10 * 1024 * 1024) 10 while len(buf): 11 try: 12 buf = buf[sock.send(buf):] 13 except socket.error, e: 14 if e.errno != errno.EAGAIN: 15 raise e 16 17 18 19 20 21
  • 15. 01 import errno 02 import select 03 import socket 04 05 sock = socket.socket() 06 sock.connect(('localhost', 1234)) 07 sock.setblocking(0) 08 09 buf = buffer('foon' * 10 * 1024 * 1024) 10 while len(buf): 11 try: 12 buf = buf[sock.send(buf):] 13 except socket.error, e: 14 if e.errno != errno.EAGAIN: 15 raise e 16 17 18 19 20 21 select.select([], [sock], [])
  • 16. 01 import errno 02 import select 03 import socket 04 05 sock = socket.socket() 06 sock.connect(('localhost', 1234)) 07 sock.setblocking(0) 08 09 buf = buffer('foon' * 10 * 1024 * 1024) 10 while len(buf): 11 try: 12 buf = buf[sock.send(buf):] 13 except socket.error, e: 14 if e.errno != errno.EAGAIN: 15 raise e 16 17 i = 0 18 while i < 5000000: 19 i += 1 20 21 select.select([], [sock], [])
  • 18. Eventlet is one of several async I/O frameworks for Python It's magic, to its detriment IMHO Co-operative co-routine scheduling Eventlet coroutines are called green threads (from Java) green threads != threads Many greenthreads in one OS thread They are very cheap We call them coroutines because they cooperatively yield to one another greenlet allows you to save a stack and switch to another stack
  • 19. 01 02 from eventlet.green import socket 03 04 05 06 07 08 09 10 11 12 13 sock = socket.socket() 14 sock.connect(('localhost', 1234)) 15 sock.send('foon' * 10 * 1024 * 1024) 16 17 18 19 20 21
  • 20. 01 import eventlet 02 from eventlet.green import socket 03 04 def busy_loop(): 05 pass 06 07 08 09 10 11 eventlet.spawn(busy_loop) 12 13 sock = socket.socket() 14 sock.connect(('localhost', 1234)) 15 sock.send('foon' * 10 * 1024 * 1024) 16 17 18 19 20 21
  • 21. 01 import eventlet 02 from eventlet.green import socket 03 04 def busy_loop(): 05 while True: 06 i = 0 07 while i < 5000000: 08 i += 1 09 10 11 eventlet.spawn(busy_loop) 12 13 sock = socket.socket() 14 sock.connect(('localhost', 1234)) 15 sock.send('foon' * 10 * 1024 * 1024) 16 17 18 19 20 21
  • 22. 01 import eventlet 02 from eventlet.green import socket 03 04 def busy_loop(): 05 while True: 06 i = 0 07 while i < 5000000: 08 i += 1 09 eventlet.sleep() 10 11 eventlet.spawn(busy_loop) 12 13 sock = socket.socket() 14 sock.connect(('localhost', 1234)) 15 sock.send('foon' * 10 * 1024 * 1024) 16 17 18 19 20 21
  • 24. Eventlet has a scheduler, twisted has an event loop Event loop is a loop (i.e. while loop) which checks for I/O events Twisted invokes callbacks for events, rather than scheduling coroutines Eventlet is confusing because magic Twisted is confusing because abstractions
  • 25. 01 02 from twisted.internet import reactor 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 reactor.run()
  • 26. 01 from twisted.internet import protocol 02 from twisted.internet import reactor 03 04 05 06 07 08 09 10 11 12 reactor.connectTCP('localhost', 1234, 13 protocol.ClientFactory()) 14 15 16 17 18 19 20 21 reactor.run()
  • 27. 01 from twisted.internet import protocol 02 from twisted.internet import reactor 03 04 class Test(protocol.Protocol): 05 pass 06 07 08 class TestFactory(protocol.ClientFactory): 09 def buildProtocol(self, addr): 10 return Test() 11 12 reactor.connectTCP('localhost', 1234, TestFactory()) 13 14 15 16 17 18 19 20 21 reactor.run()
  • 28. 01 from twisted.internet import protocol 02 from twisted.internet import reactor 03 04 class Test(protocol.Protocol): 05 def connectionMade(self): 06 self.transport.write('foon' * 2 * 1024 * 1024) 07 08 class TestFactory(protocol.ClientFactory): 09 def buildProtocol(self, addr): 10 return Test() 11 12 reactor.connectTCP('localhost', 1234, TestFactory()) 13 14 15 16 17 18 19 20 21 reactor.run()
  • 29. 01 from twisted.internet import protocol 02 from twisted.internet import reactor 03 04 class Test(protocol.Protocol): 05 def connectionMade(self): 06 self.transport.write('foon' * 2 * 1024 * 1024) 07 08 class TestFactory(protocol.ClientFactory): 09 def buildProtocol(self, addr): 10 return Test() 11 12 reactor.connectTCP('localhost', 1234, TestFactory()) 13 14 def busy_loop(): 15 i = 0 16 while i < 5000000: 17 i += 1 18 19 reactor.callLater(0, busy_loop) 20 21 reactor.run()
  • 30. 01 from twisted.internet import protocol 02 from twisted.internet import reactor 03 04 class Test(protocol.Protocol): 05 def connectionMade(self): 06 self.transport.write('foon' * 2 * 1024 * 1024) 07 08 class TestFactory(protocol.ClientFactory): 09 def buildProtocol(self, addr): 10 return Test() 11 12 reactor.connectTCP('localhost', 1234, TestFactory()) 13 14 def busy_loop(): 15 i = 0 16 while i < 5000000: 17 i += 1 18 reactor.callLater(0, busy_loop) 19 reactor.callLater(0, busy_loop) 20 21 reactor.run()
  • 31. Tulip
  • 32. Guido's "Async I/O Support Rebooted" Support for both coroutine and callback models It's event loop is called an event loop
  • 33. 01 02 03 04 import tulip 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 event_loop = tulip.get_event_loop() 28 39 30 event_loop.run_forever()
  • 34. 01 02 import socket 03 04 import tulip 05 06 sock = socket.socket() 07 sock.connect(('localhost', 1234)) 08 sock.setblocking(0) 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 event_loop = tulip.get_event_loop() 28 39 30 event_loop.run_forever()
  • 35. 01 import errno 02 import socket 03 04 import tulip 05 06 sock = socket.socket() 07 sock.connect(('localhost', 1234)) 08 sock.setblocking(0) 09 10 buf = memoryview(str.encode('foon' * 2 * 1024 * 1024)) 11 def do_write(): 12 global buf 13 while True: 14 try: 15 buf = buf[sock.send(buf):] 16 except socket.error as e: 17 if e.errno != errno.EAGAIN: 18 raise e 19 return 20 21 22 23 24 25 26 27 event_loop = tulip.get_event_loop() 28 event_loop.add_writer(sock, do_write) 39 30 event_loop.run_forever()
  • 36. 01 import errno 02 import socket 03 04 import tulip 05 06 sock = socket.socket() 07 sock.connect(('localhost', 1234)) 08 sock.setblocking(0) 09 10 buf = memoryview(str.encode('foon' * 2 * 1024 * 1024)) 11 def do_write(): 12 global buf 13 while True: 14 try: 15 buf = buf[sock.send(buf):] 16 except socket.error as e: 17 if e.errno != errno.EAGAIN: 18 raise e 19 return 20 21 def busy_loop(): 22 i = 0 23 while i < 5000000: 24 i += 1 25 event_loop.call_soon(busy_loop) 26 27 event_loop = tulip.get_event_loop() 28 event_loop.add_writer(sock, do_write) 39 event_loop.call_soon(busy_loop) 30 event_loop.run_forever()
  • 37. 01 import tulip 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 event_loop = tulip.get_event_loop() 22 23 event_loop.run_forever()
  • 38. 01 import tulip 02 03 class Protocol(tulip.Protocol): 04 05 buf = b'foon' * 10 * 1024 * 1024 06 07 def connection_made(self, transport): 08 09 transport.write(self.buf) 10 transport.close() 11 12 13 14 15 16 17 18 19 20 21 event_loop = tulip.get_event_loop() 22 23 event_loop.run_forever()
  • 39. 01 import tulip 02 03 class Protocol(tulip.Protocol): 04 05 buf = b'foon' * 10 * 1024 * 1024 06 07 def connection_made(self, transport): 08 09 transport.write(self.buf) 10 transport.close() 11 12 13 14 15 16 17 18 19 20 21 event_loop = tulip.get_event_loop() 22 tulip.Task(event_loop.create_connection(Protocol, 'localhost', 1234)) 23 event_loop.run_forever()
  • 40. 01 import tulip 02 03 class Protocol(tulip.Protocol): 04 05 buf = b'foon' * 10 * 1024 * 1024 06 07 def connection_made(self, transport): 08 09 transport.write(self.buf) 10 transport.close() 11 12 def connection_lost(self, exc): 13 event_loop.stop() 14 15 16 17 18 19 20 21 event_loop = tulip.get_event_loop() 22 tulip.Task(event_loop.create_connection(Protocol, 'localhost', 1234)) 23 event_loop.run_forever()
  • 41. 01 import tulip 02 03 class Protocol(tulip.Protocol): 04 05 buf = b'foon' * 10 * 1024 * 1024 06 07 def connection_made(self, transport): 08 event_loop.call_soon(busy_loop) 09 transport.write(self.buf) 10 transport.close() 11 12 def connection_lost(self, exc): 13 event_loop.stop() 14 15 def busy_loop(): 16 i = 0 17 while i < 5000000: 18 i += 1 19 event_loop.call_soon(busy_loop) 20 21 event_loop = tulip.get_event_loop() 22 tulip.Task(event_loop.create_connection(Protocol, 'localhost', 1234)) 23 event_loop.run_forever()
  • 43. 01 import os 02 03 def contents_of_files(dir): 04 ret = [] 05 for f in os.listdir(dir): 06 path = os.path.join(dir, f) 07 ret.append((path, file(path).read())) 08 return ret 09 10 for path, contents in contents_of_files(dir): 11 if search_for in contents: 12 print("found", search_for, "in", path) 13 break
  • 44. 01 import os 02 03 def contents_of_files(dir): 04 05 for f in os.listdir(dir): 06 path = os.path.join(dir, f) 07 yield (path, file(path).read()) 08 09 10 for path, contents in contents_of_files(dir): 11 if search_for in contents: 12 print("found", search_for, "in", path) 13 break
  • 45. 01 def gen(): 02 i = 0 03 while i < 2: 04 print(i) 05 yield 06 i += 1 07 08 i = gen() 09 print("yo!") 10 next(i) 11 print("hello!") 12 next(i) 13 print("bye!") 14 try: 15 next(i) 16 except StopIteration: 17 print("stopped")
  • 46. 01 Task = collections.namedtuple('Task', ['generator', 'wfd', 'idle']) 02 03 running = True 04 05 def quit(): 06 global running 07 running = False 08 09 while running: 10 finished = [] 11 for n, t in enumerate(tasks): 12 try: 13 next(t.generator) 14 except StopIteration: 15 finished.append(n) 16 map(tasks.pop, finished) 17 18 wfds = [t.wfd for t in tasks if t.wfd] 19 timeout = 0 if [t for t in tasks if t.idle] else None 20 21 select.select([], wfds, [], timeout)
  • 47. 01 def busy_loop(): 02 while True: 03 i = 0 04 while i < 5000000: 05 i += 1 06 yield 07 08 tasks.append(Task(busy_loop(), wfd=None, idle=True)) 09 10 11 12 13 14 15 16 17 18 19 20 21
  • 48. 01 sock = socket.socket() 02 sock.connect(('localhost', 1234)) 03 sock.setblocking(0) 04 05 def write(data): 06 buf = memoryview(data) 07 while len(buf): 08 try: 09 buf = buf[sock.send(buf):] 10 except socket.error as e: 11 if e.errno != errno.EAGAIN: 12 raise e 13 yield 14 15 def write_stuff(): 16 yield from write(b'foon' * 2 * 1024 * 1024) 17 yield from write(b'barn' * 2 * 1024 * 1024) 18 quit() 19 20 tasks.append(Task(write_stuff(), wfd=sock, idle=False)) 21
  • 49. References • My blog - http://blogs.gnome.org/markmc/2013/06/04/async-io-and-python • Eventlet - http://eventlet.net • Twisted - http://twistedmatrix.com • Tulip - http://www.python.org/dev/peps/pep-3156 • yield from - http://www.python.org/dev/peps/pep-0380