How to Wait for the Async Function to Complete in Python

Salman Mehmood Feb 02, 2024
  1. Use the await Keyword & Make an Asynchronous Function
  2. Use create_task() to Create Task to Fix an Issue
How to Wait for the Async Function to Complete in Python

This article demonstrates how to create an asynchronous function and use the await keyword to interrupt a process. We’ll also ’learn how to use tasks instead of threads in Python.

Use the await Keyword & Make an Asynchronous Function

Asynchronous programming is not multi-threading; it is not multi-processing but concurrent programming.

We will not talk about the whole idea of concurrent programming and the entire coding pattern, but we will talk about the basic principles and how we can implement those in Python.

Now let’s look at a quick example; we have a Func_1, Func_2 and Func_3, which are being called.

Func_1()
Func_2()
Func_3()

If these functions are being called asynchronously, this means that we are going to call Func_1() and then we are going to call Func_2().

When Func_1() returns so, we are only going to call Func_2(), and when Func_2() returns then we are going to call Func_3().

If we use multi-threading or multi-processing, that would not be the same as asynchronous programming. Because in multi-threading, we would define three threads in this case, and we would run all of these functions at the same time.

Or, roughly simultaneously, we will try to run them simultaneously or at least create the illusion of simultaneous execution.

But, we want to do, let’s say, Func_1() does something productive, and then it requests some data from a database, from an API, or it just sleeps in general just for the sake of waiting.

If that happens, we do not want to waste CPU time and start executing Func_2() even though this function has not yet returned. So we can only run one task simultaneously; we are not doing any multi-processing or multi-threading.

But, if the Func_1() is sleeping or waiting or being unproductive so we can utilize that time to start executing Func_2() and maybe Func_3(). To do asynchronous programming in Python, we must import a library called asyncio.

Since we will not define the whole program as asynchronous, specific functions will be asynchronous; we need to use the async keyword to specify an asynchronous function.

If we only have this Main_Func(), the whole program will be asynchronous, but we will add other functions in the next example. Inside this function, we will use two print() functions.

And, in between, we are going to sleep, but we are not going to sleep with time.sleep(); we are going to use asyncio.sleep().

We need to use the await keyword before calling asyncio.sleep(), which means that we will wait for the second print statement to finish. Before finishing, we are not going to do anything else.

To run the Main_Func() function we need to use asyncio.run() and inside run() function we will pass Main_Func() function. We must call the Main_Func() function; we are not just referring to it as multi-threading.

import asyncio


async def Main_Func():
    print("Before waiting")
    await asyncio.sleep(1)
    print("After waiting")


asyncio.run(Main_Func())

Output:

python wait for the async function to complete - output one

Let’s introduce another asynchronous function called Func_2(); we will print two statements and sleep for two seconds.

Inside the Main_Func() function, instead of sleeping, we call the Func_2() function with the await keyword, but that will not be asynchronous.

import asyncio


async def Main_Func():
    print("Before waiting")
    await Func_2()
    print("After waiting")


async def Func_2():
    print("Func_2: Before waiting")
    await asyncio.sleep(2)
    print("Func_2: After waiting")


asyncio.run(Main_Func())

Since we are awaiting the function, which is the same as just calling it asynchronously, it will not execute this until all the instructions are done as we defined.

Before waiting
Func_2: Before waiting
Func_2: After waiting
After waiting

It is not asynchronous; however, if we want to do something like that when the Main_Func() function calls, then the control should print the first print statement of the Main_Func() function.

And then, call the Func_2() function, thus printing this function’s first print statement.

While this function is sleeping, it should print the second print statement of the Main_Func() function, and once this is done, it should print the second print statement of the Func_2() function.

Use create_task() to Create Task to Fix an Issue

To do that, we need to work with tasks so, at the beginning of the Main_Func() function, we are going to create a task while calling asyncio.create_task(), and inside the task, we will pass Func_2().

It means that once we have some idle time, we will call that task.

import asyncio


async def Main_Func():
    Task = asyncio.create_task(Func_2())
    print("Before waiting")
    print("After waiting")


async def Func_2():
    print("Func_2: Before waiting")
    await asyncio.sleep(2)
    print("Func_2: After waiting")


asyncio.run(Main_Func())

After running the code, we can see the two print statements are printed from the Main_Func() function then it is done. And the first print statement is executed, but the execution is terminated before printing the second print statement.

Before waiting
After waiting
Func_2: Before waiting

It is because the Main_Func() is the main function, the control is not waiting for the Func_2() function, which means that once the control reaches the end of the Main_Func() function, the control stops executing.

The control does not need to wait for the second print statement of the Func_2() function to finish so that the control will skip it. To fix it, we will use await Task at the end of the Main_Func() function.

import asyncio


async def Main_Func():
    Task = asyncio.create_task(Func_2())
    print("Before waiting")
    print("After waiting")
    await Task


async def Func_2():
    print("Func_2: Before waiting")
    await asyncio.sleep(2)
    print("Func_2: After waiting")


asyncio.run(Main_Func())

Now we can see that it is printed as it was defined.

Before waiting
After waiting
Func_2: Before waiting
Func_2: After waiting

If we want to see how this works asynchronously, we can do it using the sleep() function in between print statements.

It means we will execute a first print statement of Main_Func(), and then the control will sleep for a second, which means that the main function now has idle time.

And now, the task has time to be executed until the Main_Func() is entirely run. Since the Main_Func() function is sleeping means we now have CPU time available to start executing the Func_2() function by calling it using the task.

But, the Func_2() function also goes to sleep, which means that inside this function control waits for two seconds, and the control goes to the Main_Func() function to print a second print statement.

Then it terminates, meaning the control is no longer interested in the rest of the Func_2() function.

async def Main_Func():
    Task = asyncio.create_task(Func_2())
    print("Before waiting")
    await asyncio.sleep(1)
    print("After waiting")

Output:

Before waiting
Func_2: Before waiting
After waiting

If we want to be interested in that, we have to use await Task inside at the end of the Main_Func() function.

It is asynchronous; as you can see, the order is that the Main_Func() function prints the first print statement, then Func_2() prints first, then Main_Func() prints the second as well as Func_2() prints the second.

Because when the function goes to sleep, idle time is used so that no CPU time is wasted.

python wait for the async function to complete - output two

Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

Related Article - Python Async