This tutorial will provide a complete detail about asynchronous
for loops in Python. We will discuss the asynchronous function, asynchronous
for loop, and
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.
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.
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
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):
async is added to declare this function as an asynchronous function.
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:
Note: The keyword
awaitis required to call every asynchronous function, whether it is from the library or a user-defined function.
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.
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
The syntax is:
results = await asyncio.gather(fun_a(5), fun_b(5))
Here, we are making a pipeline of
fun_b so they can run concurrently.
The event loop is the main ingredient of every asynchronous application. Event loops run asynchronous functions.
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.
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:
This statement will run the code concurrently if the
main function is asynchronous.
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_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.
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
[1, 2] is the tuple received by the
main function from our asynchronous functions.
2 are returned by our asynchronous functions and arranged in the order we wrote these functions in the