This tutorial was written on top of Python 3.6. This is taken from my book “Learning Concurrency in Python” if you wish to read up more on the library.
Asyncio became part of the Python ecosystem in version 3.4 and has since then become the basis for a huge number of Python libraries and frameworks due to it’s impressive speed and ease of use. Asyncio allows you to easily write single-threaded concurrent programs that utilize something called coroutines, these coroutines are like a stripped down threads and don’t come with the same inherit performance issues that your full-fat threads would typically come with.
Asyncio also does a very good job of abstracting away from us the complexities of things such as multiplexing I/O access over sockets and it also simplifies our jobs by providing an arsenal of synchronization primitives that enable us to make our programs thread-safe.
In order to get started with asyncio we require one crucial component, that is an event loop. All asyncio based systems require an event loop, this is the crux of our programs performance. The event loop schedules our
asyncio.coroutines and handles all of the heavy lifting.
We can define an event loop that will simply execute on coroutine like so:
When you run this you should see that our
myCoroutine() successfully executes. Now at this point you must be asking, this doesn’t give us anything but extra code, what’s the fuss all about? Well for this example it doesn’t provide much benefit, however in more complex scenarios, that’s when we really see the true performance benefits.
I would recommend checking out my tutorial on Creating a REST API in aiohttp and Python. This provides a more complex example and is a good example as to how performant asyncio can be.
coroutines are essentially lightweight versions of your more traditional threads. By using these we essentially enable ourselves to write asynchronous programs that are very similar to threads but they run on top of a single thread. We can define
coroutines in 2 distinct ways.
The first method was introduced in Python 3.5 and I would tend to push you towards using this method over the latter.
Futures in asyncio are very much similar to the
Future objects you would see within Python
ProcessPoolExecutors and tt follows an almost identical implementation. Future objects are created with the intention that they will eventually be given a result some time in the future, hence the name. This is beneficial as it means that within your Python program you can go off and perform other tasks whilst you are waiting for your
Future to return a result.
Thankfully working with Futures in asyncio is relatively easy thanks to the
ensure_future() method which takes in a
coroutine and returns the
Future version of that
If you were to run this you should see that our program successfully turns our
coroutine into a
future object and prints out the result.
Let’s now try to take advantage of asyncio’s ability to run multiple coroutines concurrently. This will hopefully give you some idea as to how powerful
asyncio is and how you can use it to effectively create incredibly performant Python programs running on a single-thread.
Let’s start by creating a simple coroutine that takes in an
id as its primary parameter. This will generate a random integer called
process_length and wait for that length of time. It will then print out it’s
id and how long it awaited for.
Next within our
main() method we will generate 10 tasks that and then await these tasks completion using the
await asyncio.gather() function, passing in our list of
tasks. Finally we’ll utilize the same event loop from the previous example in order to run our
When you run this you should see something like so:
Our coroutines go off and execute concurrently and finish execution at different times. It’s important to note that these are not completed in the same order as they were submitted and if you were to time the execution of the above program, it would take just above 5 seconds to complete execution.
This was just a very quick and simple introduction to the
asyncio framework. We’ll be covering this framework in more detail in future tutorials.