DEV Community

Periklis Gkolias
Periklis Gkolias

Posted on • Originally published at hackernoon.com on

Asyncio, the invincible

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())
Enter fullscreen mode Exit fullscreen mode

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.

Originally published at perigk.github.io.


Latest comments (5)

Collapse
 
tamas profile image
Tamás Szelei

Coming from a C++ background where I did a bit of async programming with asio, I found asyncio hard to grasp. I stumbled upon trio, which was much closer to my mental model and vocabulary. I recommend checking it out for anyone who struggles like I did.

Collapse
 
perigk profile image
Periklis Gkolias

Indeed, trio looks really nice. In a "part 2" kindof article, I will dive into frameworks and trio will totally be in.

trio.readthedocs.io/en/latest/

Collapse
 
florimondmanca profile image
Florimond Manca

It seems Python asynchronous programming is gaining momentum but still is quite hairy to get started with, so it's good to see this kind of quick intros popping up. Thanks. :-)

I just wanted to note that the async flow diagram you expose in your article is a bit misleading, as it is demonstrating one specific implementation of asynchronous programming — i.e. callback style async. I heard that this is how Tornado was implemented originally, but that asyncio uses a different async implementation.

From what I know, asyncio uses generators to implement coroutines, i.e. functions that can be "paused" and "resumed" at anytime. These tasks are run by the event loop (probably in a round-robin fashion), such that every time a task awaits, it gives control back to the event loop which allows the next task to run for a bit, until it awaits or terminates.

This cooperative style is what justifies why, as you noted, async is "all-in": if any task blocks, the whole thing collapses back into a good ol' synchronous flow.

So, in this sense, asyncio is more task-based than callback-based. :-)

Collapse
 
perigk profile image
Periklis Gkolias

Thanks for making that clear, I wanted to avoid mentioning such hairy details in an introductory article. :)

As I am saying in the article,

explaining a potential async flow.

.

Collapse
 
florimondmanca profile image
Florimond Manca

Sure! Async can be tough to wrap one’s head around, so it was a good idea to stick to a high-level intro here.