Asynchronous programming in python

AsyncIO & Asynchronous Programming | Python

Are you tired of waiting for your code to complete a long-running task before moving on to the next one?
If so, asynchronous programming may be the solution you’ve been looking for. In this article, we’ll explore what asynchronous programming is, why it’s useful, and how to use it in Python.

What is Asynchronous Programming?

In simple words, asynchronous programming allows the execution of multiple tasks simultaneously.

This can lead to faster program execution, particularly for I/O-bound tasks like network requests and file I/O.

Note: One should not confuse Asynchronous Programming with Multithreading since both may appear similar at first but are actually very different.

In Asynchronous Programming, tasks run simultaneously on a single thread and share the same memory stack. On the other hand, in Multithreading, tasks run concurrently on multiple threads, and they have separate memory allocations.

Here is a video that explains Asynchronous in Detail:

Real Life Example

To illustrate the difference between synchronous and asynchronous programming, let’s consider the example of a car mechanic refilling oil in two cars.
In a synchronous scenario, the mechanic would refill the oil in one car, wait for the task to complete, and then move on to the second car.

In the traditional synchronous way, the mechanic would have to drain and refill the oil in one car first before moving on to the next car. This can take a lot of time and can be inefficient.

However, asynchronously, the mechanic would drain the oil from both cars at the same time, and then refill the oil in both cars simultaneously.

That means he first started draining the oil from Car 1 then while it was draining he went to Car 2 to start draining its oil

draning car oil at the same time
Mechanic Draining car 2 oil while car 1 oil is draning by itself

This approach can save a lot of time and effort, as the mechanic can perform the tasks concurrently, making the process much faster and more efficient.

Async, Await, and the Asyncio Module

Python implements asynchronous programming using the async and await keywords and the asyncio module.
To define a coroutine, which is a type of function that can be paused and resumed at any point during execution, the async keyword is used.
To wait for a coroutine to complete before moving on to the next line of code, the await keyword is used.

The asyncio module provides a framework for managing coroutines and scheduling their execution. It includes functions for creating coroutines, managing event loops, and performing I/O-bound tasks.

Asynchronous Programming Example

Let’s take a look at an example of asynchronous programming in Python. Suppose we have three functions, f1(), f2(), and f3(), each of which takes some time to complete:

In this synchronous example, the functions are executed one after the other, resulting in a total execution time of 1.5 seconds.

import time

def f1():
    print("Running function 1 !!")
    time.sleep(0.5)
    print("Function 1 Ran Successfully :) ")

def f2():
    print("Running function 2 !!")
    time.sleep(0.5)
    print("Function 2 Ran Successfully :) ")

def f3():
    print("Running function 3 !!")
    time.sleep(0.5)
    print("Function 3 Ran Successfully :) ")

def main():
    f1()
    f2()
    f3()

main()

Now let’s convert this code to use asynchronous programming:

import asyncio

async def f1():
    print("Running function 1 !!")
    await asyncio.sleep(0.5)
    print("Function 1 Ran Successfully :) ")

async def f2():
    print("Running function 2 !!")
    await asyncio.sleep(0.5)
    print("Function 2 Ran Successfully :) ")

async def f3():
    print("Running function 3 !!")
    await asyncio.sleep(0.5)
    print("Function 3 Ran Successfully :) ")

async def main():
    await asyncio.gather(f1(), f2(), f3())

asyncio.run(main())

In this asynchronous example, the functions are executed concurrently, resulting in a total execution time of only 0.5 seconds.
The asyncio.sleep() function is used to simulate I/O-bound tasks that can be executed concurrently. In simple words, it simulates the time it takes to run a function.

Conclusion

In conclusion, asynchronous programming is a powerful technique that can greatly improve the performance of your Python programs.
By using the async and await keywords, as well as the asyncio module, you can write code that executes tasks concurrently, resulting in faster and more efficient code.