Oslo/blueprints/asyncio

Authors

 * Victor Stinner - victor.stinner@enovance.com

Rationale
The Enovance company is working actively on porting OpenStack on Python 3, see the status on the Python3 page. Eventlet dependency blocks the portage because it is not yet compatible with Python 3. Even if it would be available, we would like to get ride of eventlet for the reasons listed below.

We choose to start the work in the Olso Messaging project because its design allows to use different "executor drivers", a function to run a task asynchronously. Olso Messaging is a core component and so should be ported on Python 3 first to be able to port other components on Python 3.

The asyncio module is a new and modern asynchronous library which is part of the Python 3.4 standard library. The idea is to add a new asyncio executor to Olso Messaging. At the beginning, asyncio will reuse the greenlet event loop. If an OpenStack server doesn't use eventlet anymore, it will be possible to use an asyncio event loop.

What's wrong with eventlet?
Eventlet is “a concurrent networking library for Python that allows you to change how you run your code, not how you write it” according to its documentation.

Eventlet uses monkey-patching on the Python standard libraries to replace blocking functions with asynchronous functions using greenthreads. For example, the Python time.sleep function which “suspends execution for the given number of seconds” is replaced with greenthread.sleep which “yields control to another eligible coroutine until at least seconds have elapsed”.

All greenthreads are running in the same operating system thread. With monkey-patching, Python threads are replaced with greenthreads. There is no real concurrency, only one greenthread is running at the same time.

Implicit asynchronous code causes a new kind of race condition issues which are difficult to understand and to fix. It is hard to guess where the scheduler may switch tasks. The source code of a function should be carefully read to check if it may yield control to another coroutine or not. A function of an external module may be modified later to use a blocking function.

Eventlet relies on the greenlet module to manage greenthreads. The greenlet module uses assembler code with one version per architecture and per platform to switch between green threads. Greenlet contains code specific to CPython and so cannot be used with PyPy or Jython. Even if “it works”, it will not be integrated in Python, it is difficult to maintain and so is not a sustainable solution.

The eventlet module does not support Python 3 yet, see the Support Python 3.3 issue. The availability of eventlet on Python 3 would not change anything, we want to replace it for all the reasons listed above.

Why using asyncio and not yet another asynchronous library?
The asyncio module has be designed as a superset of existing libraries: Twisted, Tornado, gevent, eventlet, etc. The design is the PEP 3156 written by Guido van Rossum who also wrote the Python language. The PEP has been written with the help of various developers and the design reuses many good ideas of existing libraries. Asyncio offers a nice syntax for coroutines using the new "yield from" syntax of Python 3.3.

The PEP 3156 has been accepted and asyncio is part of the Python 3.4 standard library. For Python 3.3, the third party project Tulip can be used. Enovance ported asyncio on Python 2.6 and 2.7 as the new Trollius project which is based on Tulip. Trollius uses "yield" instead of "yield from" and "return x" must be replaced with "raise Return(x)". Except of that, the API is the same. Enovance also wrote the documentation of the asyncio module: asyncio – Asynchronous I/O, event loop, coroutines and tasks.

Smooth integration of asyncio in Olso Messaging: greenio
The greenio project allows to "plug" asyncio in eventlet: it is an event loop compatible with asyncio but using greenlet functions like greenlet.switch. So it becomes possible to use the new asyncio API, but existing OpenStack code doesn't need to be changed and will still use eventlet.

Links

 * Add an new Olso Messaging executor using asyncio blueprint
 * Add a asyncio executor to oslo.messaging blueprint (duplicate)
 * tulip executor (impl_tulip.py) in Oslo Incubator
 * Olso Messaging: openstack-dev: Oslo messaging API design and Async I/O and Python by Mark McLoughlin
 * Python3
 * asyncio: asyncio documentation, PEP 3156, Tulip, Trollius
 * greenio