Async for Loop in Python

Abdul Mateen Oct 10, 2023
  1. Asynchronous Function in Python
  2. Asynchronous for Loop in Python
Async for Loop in Python

This tutorial will provide a complete detail about asynchronous for loops in Python. We will discuss the asynchronous function, asynchronous for loop, and sleep concepts.

Next, we will discuss the Python library asyncio and the functions required to run asynchronous code. Finally, we will see a couple of examples in Python to fully understand the concept.

Asynchronous Function in Python

Asynchronous functions help run heavy tasks (like batch programs, maybe we are interested in running processes in the background) in parallel to other functions of the same program. It is possible to run functions in parallel when functions are not dependent on each other or not entirely dependent on each other.

A synchronous function returns control once the task is completed, whereas an asynchronous function returns control to run other functions/code in parallel and gets back control after some time. In this way, not only the heavy task is completed with many other tasks also completed in parallel.

Technically, a synchronous function blocks the control of the main function, whereas an asynchronous function executes without blocking the main function. This way, the main function can run multiple asynchronous functions in parallel.

Asynchronous for Loop in Python

For synchronous loops, they execute without any pause/giving control; however, to make them asynchronous, we have to define them in some asynchronous function. Also, we need to sleep in this process for some duration to give control to some other function.

Use the sleep Statement

A process/thread/function may go to sleep for some time; you may consider it a break. However, the purpose is to lose control for some duration.

As a result, some other function gets the control. After some duration, the control goes back, and the function resumes.

Now, it’s time to move towards implementation in Python. We will discuss the syntax part step by step, and at the end, we will show the complete code.

Python Library and Functions

The asyncio is a library in Python to write concurrent programs/functions using the async/await syntax. The async is the keyword used (to create the asynchronous functions) at the start of every function.

The syntax is:

async def fun_a(t):

Here async is added to declare this function as an asynchronous function.

The sleep function can suspend the execution of a coroutine for some duration. Coroutines are the processes/functions that make a pipeline structure during execution.

This function voluntarily leaves the CPU for another cooperative task through the await keyword. The syntax of the sleep function is:

await asyncio.sleep(1)

Note: The keyword await is required to call every asynchronous function, whether it is from the library or a user-defined function.

The await keyword returns the control to the event loop. You may consider that if an asynchronous function calls with the await command, the sleep statement (inside the for loop) controls the cooperative process until sleeping.

The gather function combines multiple cooperative processes (technically making a coroutine) to run as a unit. This function returns a tuple of results in the order of functions written in the gather call.

The syntax is:

results = await asyncio.gather(fun_a(5), fun_b(5))

Here, we are making a pipeline of fun_a and fun_b so they can run concurrently.

The event loop is the main ingredient of every asynchronous application. Event loops run asynchronous functions.

The get_event_loop() method checks if set_event_loop is not called yet, and it will create an event loop and set it as current. The syntax is:

my_loop = asyncio.get_event_loop()

If this command is executed a second time when the loop is already created, it will do nothing. However, in the first call, no loop is created; therefore, it will create an asynchronous loop.

The run_until_complete() is used to run the event loop concurrently if the loop returned by the get_event_loop() is asynchronous. The syntax is:

my_loop.run_until_complete(main())

This statement will run the code concurrently if the main function is asynchronous.

Asynchronous Code

Having a clear idea about the concept and the Python library required to run asynchronous function/routine/process, it’s time to see a complete coding example:

import asyncio


async def fun_a(t):
    for i in range(t):
        print("fun_a", end=" ")
        await asyncio.sleep(1)
    return 1


async def fun_b(t):
    for i in range(t):
        print("fun_b", end=" ")
        await asyncio.sleep(1)
    return 2


async def main():
    results = await asyncio.gather(fun_a(5), fun_b(5))
    print(results)


my_loop = asyncio.get_event_loop()
my_loop.run_until_complete(main())

In this code, on the top (the very first line), we are importing the asyncio library. This library has a required function for calling asynchronous functions to run concurrently; they are already discussed with syntax.

Next, we have two asynchronous functions—fun_a and fun_b, which we want to run concurrently. Again, we want to call asynchronous functions from the main function. Therefore, the main is also created as an asynchronous function.

Also, note that we pass 5 to our function to run loops inside it five times. So later, you can see the output and get the idea that the loop is not running completely; each goes to a sleep state and gives control to the other function.

We will repeat this point after the output.

Inside the main function, we have called the gather function and passed our asynchronous functions so that they can run in parallel. The gather function returns a tuple, having two values returned from our target asynchronous functions.

We are finally coming to the last two lines. In the second last line, we called the get_event_loop function to create a loop. In the last line, using our loop, we called the run_until_complete function to start running our main function asynchronously.

The output of this code is:

fun_a fun_b fun_a fun_b fun_a fun_b fun_a fun_b fun_a fun_b [1, 2]

First, note that our loops are not running completely like conventional codes; instead, both loops are running concurrently. You can see the result of both functions print statements.

Lastly, [1, 2] is the tuple received by the main function from our asynchronous functions. 1 and 2 are returned by our asynchronous functions and arranged in the order we wrote these functions in the gather function.

Related Article - Python Loop