Getting Started with Asynchronous Code in Python

For better viewing, tilt your cellphone horizontally in landscape mode. 

If you use python programming language, you would probably know it’s a synchronous “or blocking” language, meaning every line of code is read, interpreted, and executed sequentially. The problem with synchronous programming is that every line of code is interpreted and executed before moving on to the next line.

Say, for example, you made a function for web scrapping or sending an email and that takes time to render the results. The program will not move on to the next line of code until the first one is completed, and this adds delays to the program. I have this problem in my web applications where I need to send a welcome email to my new subscribers without waiting for the web page to finish loading.

Let’s look at the synchronous code below.

Here there are two functions, the message function takes two parameters (i.e. First Name and Last Name) and returns a string message. This function is read but only executed when called in the mainfunction. now let’s assume the mainfunction is the primary block of code and if you run this whole block of code in your IDE you will get the following output on your terminal.

D:\My Projects\Test Lab>py async.py
message function executed
Main Function Executed

Now let’s say the message function takes around 5 seconds to return the output, so how much time the whole application takes time? We are going to add the 5 seconds delay in the message function.

I’ve imported the time module to add a delay of 5 seconds in the message with time.sleep(5). I also imported the datetime module to calculate how much time it takes to take a function to return the result. It’s obvious here that takes 5 seconds but I use this often in my codes where I am not certain of the delay.

Anyhow, here is the obvious output in the terminal.

D:\My Projects\Test Lab>py async.py
Message function executed in total 5.01 seconds
Main Function Executed

If we look that way the whole application takes 5 seconds to execute. But what if we don’t want that? To solve this we can do asynchronous programming without waiting for the synchronous function (message function) to execute.

I am going to put a condition here that we want to keep the message and mainfunction as synchronous functions and make no changes in these codes. So, the strategy will be that we want to create a new asynchronous function to call the message function and run coroutine without affecting the performance of mainfunction.    

Let me explain what is going on here. First, I imported the asyncio module and right after the message function, I created a new asynchronous function “message_task”. This new function converts my synchronous message function to asynchronous. Remember the condition is that we don’t want to make changes to our message function.

After that, I created another async function “tasker” which will be the scheduled coroutine task that will run in the background whenever a new task is created. In the main function, I called the tasker function and passed on the parameters. Here are the results.

D:\My Projects\Test Lab>py async.py
Main Function Executed
Message function executed in total 5.01 seconds

 

You can clearly see that the main function is executed first and the message function returns the results once completed.  You can compare the results with our previous synchronous code as below.

D:\My Projects\Test Lab>py async.py
Message function executed in total 5.01 seconds
Main Function Executed

Using asynchronous programming allows you to run multiple tasks concurrently within a single thread and this improves the performance and responsiveness of the application. You can use the approach when you want to run any block of code in background like sending an email or doing web scrapping that requires alot of time to return the results.   

 

Eiraj Amin

Created on: March 25, 2023