Professional Documents
Culture Documents
Keep a UI responsive
avoid beach ball while loading a url
Downsides
Too many choices Nobody likes callbacks APIs not always easy Standard library doesn't cooperate
Monkey-patching
"patch-and-pray"
So what to do?
No, really!
Interop
Most frameworks don't interoperate There's a small cottage industry adapting the event loop from framework X to be usable with framework Y
Tornado now maintains a Twisted adapter There's also a zeroMQ adapter for Tornado I hear there's a gevent fork of Tornado etc.
Tulip:
experimental prototype (currently) reference implementation (eventually) additional functionality (maybe) works with Python 3.3 (always)
Basic callbacks
call_soon(callback, *args) call_later(delay, callback, *args) call_repeatedly(interval, callback, *args) call_soon_threadsafe(callback, *args)
All return a Handler instance which can be used to cancel the callback
I/O callbacks
add_reader(fd, callback, *args) -> Handler remove_reader(fd) add_writer(fd, callback, *args) -> Handler remove_writer(fd)
Not all fd types are always acceptable fd may be an object with a fileno() method
UNIX signals
add_signal_handler(sig, callback, *args) -> Handler remove_signal_handler(sig) Raise RuntimeError if signals are unsupported
Thread interactions
wrap_future(future) -> Future run_in_executor(executor, callback, *args) -> Future Used to run code in another thread
sometimes there is no alternative e.g. getaddrinfo(), database connections
Um, Futures?
Like PEP 3148 Futures (new in Python 3.2):
from concurrent.futures import Future f.set_result(x), f.set_exception(e) f.result(), f.exception() f.add_done_callback(func) wait(fs, [timeout, [flags]]) -> (done, not_done) as_completed(fs, [timeout]) -> <iterator>
Um, coroutines?
Whoops, let me get back to that later
What's a Future?
Abstraction for a value to be produced later
Also known as Promises (check wikipedia) Per wikipedia, these are explicit futures
API:
result() blocks until result is ready an exception is a "result" too: will be raised! exception() blocks ands checks for exceptions done callbacks called when result/exc is ready
is equivalent to:
data = <equivalent_blocking_function>
...and keep calm and carry on Also forget about result(), exception(), and done-callbacks
Error handling
Futures can raise exceptions too Just put a try/except around the yield-from: try: data = yield from loop.sock_connect(s, h, p) except OSError: <error handling code>
Coroutines
Yield-from must be used inside a generator Use @coroutine decorator to indicate that you're using yield-from to pass Futures Coroutines are driven by the yield-from Without yield-from a coroutine doesn't run
Tasks
Tasks run as long as the event loop runs A Task is a coroutine wrapped in a Future Two ways to create Tasks:
@task decorator (instead of @coroutine) f = Task(some_coroutine())
The Task makes sure the coroutine runs Task is a subclass of Future
Only this abstraction level supports both ready- (select) and done-callbacks (IOCP)
Tulip (3rd party) will work with vanilla 3.3 Will keep Tulip around for a few releases PS. stdlib version won't be named "tulip"
Consider this a carrot for porting to 3.3 :-) However, someone could implement a PEPconforming event loop in Python 2.7
just use yield instead of yield-from
Acknowledgments
Greg Ewing for PEP 380 (yield-from) Glyph and SF Twisted folks for meetings Richard Oudkerk for the IOCP proactor work Nikolay Kim for much of the code and tests Charles-Franois Natali for the Selectors Eli Benderski, Geert Jansen, Sal Ibarra Corretg, Steve Dower, Dino Viehland, Ben Darnell, Laurens van Houtven, Giampaolo Rodol, and everyone on python-ideas...