Bitperi(Periklis Gkolias)

Productivity tips and coding for thriving people

Asyncio, the invincible

TL;DR / Intro

Async programming is the new sexy when it comes to multitasking. It became famous with NodeJS but you can find libraries that support it in most major languages.

For example in Python, the two most famous approaches are the usage of Tornado Web Server and the built-in library asyncio. For today we will do an introduction to the latter, as it has gone through tons of iterations and improvements lately and it is ready to charm people with its intuitive approach.

What is async programming?

It is a programming approach where we are vigilant when it comes to “dead time”. For example, if I/O is happening (eg I just sent a GET request, waiting for a response), the application can continue doing other stuff. Some people call it, the ideal secretary effect.

It might not be for Python, but the article here has a great diagram explaining a potential async flow.

Async flow

What’s wrong with multithreading?

A program is using multithreading when there are various threads to perform the tasks needed. This requires a lot of care, coordination, and proactivity, as threads need at the very least to not lock each other out of a shared resource(deadlock). Not to mention the extra overhead in memory, as threads need to have access on own copies of data.

Here you can find a related StackOverflow thread.

Not that multithreading is useless. On the contrary, some operations are synchronous in nature. For example, deleting a huge file from your filesystem. Some people might say that you can overcome this by using a stream-based approach and delete one small chunk at a time and they are right, I am just trying to demonstrate a point. :-)

Async programming even though it can work together with multithreading, can work effectively with only one thread as well. And most of the times, you cannot tell the difference in performance (I will visit that matter in a later article). The only “overhead” here, is to know that writing commands one after another doesn’t mean they will be executed in the same sequence

Asyncio - I choose you

asyncio is a library to write concurrent code using the async/await syntax. In that way, even though you write asynchronous code, you end up with a synchronous visual perception of it, which makes maintainability a bit easier.

So here is how to write async code with python, with comments to explain each step

# First import the library that provides all those bells and whistles
import asyncio

# Import datetime and calendar as our example is based on date handling
import datetime
import calendar


# Here is the important part. We declare a function as async. That means its execution
# will not block the application. For example, if you run the function outside
# of an async context it will print something like: 
# <coroutine object show_me_the_day at 0x7f89d55a0e60> 
# and not the result you would expect in a synchronous execution.
async def show_me_the_day():
    # Calendar is not asynchronous, so we duse asyncio.sleep to emulate the async nature
    # If for any reason you want to block the execution while
    # an async function is executed (eg you need the return value), use await.
    # Await can only be used in async functions, and only inside async functions
    await asyncio.sleep(1)
    return calendar.day_name[datetime.date.today().weekday()]


async def main():
    # If for any reason you want to block the execution while
    # an async function is executed (eg you need the return value), use await.
    # Await can only be used in async functions, and only inside async functions
    day = await show_me_the_day()
    print('Yo, today is ', day)
   
asyncio.run(main())

Apart from little boilerplate, it is like you are reading a classic sequential script. Classic Python magic :)

Beware though

There is one big caveat when using asyncio. This is, that we must rely on asynchronous libraries when it comes to I/O. Otherwise, the gain is negligible.

Conclusion

Thank you for reading this article, I hope you liked it. Python has done a lot of improvements in the way it handles asynchronous programming, during the last version. As always, a joy and a masterpiece together. I will come back with a performance-oriented article and maybe a couple of frameworks that are around.

If you want to dig deeper, the official documentation is very great, please have a look.

comments powered by Disqus