Asynchronous Programming in Python

asyncio module helps in achieving asynchronous programming in Python. It gives the support for async / await keywords, similar to javascript. Let us directly dive into example code snippet and discuss it in details.

import asyncio

async def f1():
   print('started execution of f1')
   await asyncio.sleep(1)
   print('exiting from f1')
   return 'f1_return_value'

async def f2():
   print('started execution of f2')
   await asyncio.sleep(1)
   print('exiting from f2')

async def my_async_function():
   print('started execution of my_async_function')
  
   # do somethings in asynchronous manner
   # as an example, let's sleep for 1 second
   await asyncio.sleep(1)

   ret = await f1()
   print(ret)

   print('-'*20)

   task1 = asyncio.create_task(f1())
   task2 = asyncio.create_task(f2())
   await asyncio.gather(task1, task2)

   print('exiting from my_async_function')

asyncio.run(my_async_function())

print('line at the end')

At the beginning, we import the asyncio module. This is built-in in Python and requires no extra package installation.

In the function definition, we add the keyword async in front of def keyword. This results in wrapping the function by another function and making it return a coroutine object.

There are 3 ways of running code of an async function - keyword await, asyncio.run function and asyncio.create_task function. Let’s look at them one by one.

The keyword await can be used preceding call to an async function. It does 2 things - it runs the code of the function and also waits for its completion.

asyncio.run function should be used at the entry point of the async stack and should ideally be used once. It executes the coroutine and returns the result.

asyncio.create_task function can be used to create a background task. For example, in our snippet, we created 2 tasks - task1 and task2. After the task creation, we waited for both the tasks to complete using await on asyncio.gather function.

The output of our snippet looks like below.

> python ./test_for_blog.py
started execution of my_async_function
started execution of f1
exiting from f1
f1_return_value
--------------------
started execution of f1
started execution of f2
exiting from f1
exiting from f2
exiting from my_async_function
line at the end

From the above output logs, we can clearly see that task1 and task2 were running in parallel, as their log-lines got mixed.

Refer here, for detailed documentation.

Kedar Chandrayan

Kedar Chandrayan

I focus on understanding the WHY of each requirement. Once this is clear, then HOW becomes easy. In my blogs too, I try to take the same approach.