Let’s learn how to do asynchronous programming in Python using the asyncio module.

Asynchronous programming in this context refers to the programming paradigm where distinctive units of codes execute in parallel instead of sequentially. Asynchronous programming is particularly useful for cases where your application has to wait for the result of requests sent to external resources such as databases, webpages, REST APIs etc. With asynchronous programming, you can write applications that are more responsive and user-friendly.

There are several ways to implement asynchronous functions in Python, including via multithreading, multiprocessing, and other multitasking techniques. In addition to these, the default Python installation comes with a module called asyncio that allows you to write asynchronous function at the programming level in Python. Today we’re going to show you how to do it.

Basic Python Asynchronous Programming with Asyncio

The following script imports the asyncio module and then defines two functions: parent_func() and child_func1(). Notice the keyword async before the function definition. You need to use this keyword to define asynchronous functions with the asyncio module.

Inside the parent_func() function, which we’ll refer to as parent function in this tutorial, the function child_func1() is called asynchronously using the create_task() method from the asyncio module. The child_func1() function will start executing whenever the parent_func() is stuck and waiting for the result of some external request.

Next, inside the parent_func() function you print a statement “Item 1” and then add a sleep of 2 seconds using the asyncio.sleep() method. This sleep() function is called to imitate the behavior where a function is waiting for the result of a request sent to an external resource. As soon as the sleep() function executes the parent_func() goes to the wait state and the child_func1() starts executing. The child function prints two strings on the console.

After two seconds, the parent_func() again starts executing which prints the string “Item 2” on the console. Set up your functions with this code:

import asyncio

async def parent_func():

    #function to call if current function
    #is waiting for something
    task = asyncio.create_task(child_func1())

    print("Item 1")

    #add sleep to add a dummy wait
    await asyncio.sleep(2)
    print("Item 2")


async def child_func1():
    print("Price 1")
    print("Price 2")

To run an asynchronous function, you need to pass that functions call statement as a parameter value to the run() method of the asyncio module as shown below.

asyncio.run(parent_func())

Warning: If you’re testing this in Jupyter notebook or IPython, there’s a good chance the run statement above will generate a *RuntimeError: asyncio.run() cannot be called from a running event loop” error. That’s because Jupyter is already running an event loop. You’ll need to replace the line above with await(parent_func()).

The output below shows that the parent_func() function prints the string “Item 1” on the console and then it goes to sleep for 2 seconds. During those 2 seconds, the child_func1() executes in parallel and prints strings “Price 1” and “Price 2” on the console. Finally, after 2 seconds, the parent_func() again starts executing and prints the string “Item 2” on the console.

Output:

Item 1
Price 1
Price 2
Item 2

Want to do more with Python?

We've uncovered a lot more tricks to help you get the most out of Python. To take your Python programming to the next level, enter your email address below and we'll send you our most powerful Python tricks yet.

Yes, show me more free Python tips

Waiting for a Function Execution using Await keyword

In the previous section, you use the await keyword to implement the sleep() function inside the parent_func() function. The await keyword can also be used to wait for a function to complete its execution before the parent function completes its execution.

Let’s see an example where one asynchronous function completes execution without letting the other asynchronous function finish its execution.

The following script is similar to the previous script except for the third line in the child_func1() function where we add a sleep of 4 seconds before the second print statement.

Now if you call the parent_func() function using the run() method from the asyncio module, the string “Item 1” will be printed on the console, next the parent_func() will sleep for 2 seconds and during that period the asynchronous function child_func1() executes, printing the string “Price 1” on the console. It then sleeps for 4 seconds. After 2 seconds of sleep, the parent_func() again starts executing and prints the string “Item 2” on the console and finishes execution.

Since the sleep time for the function child_func1() is 4 seconds, the second print statement in the child_func1 function, which prints the string “Price 2” is not executed and you’ll only see three strings in the output of the following script.

import asyncio

async def parent_func():

    #function to call if current function
    #is waiting for something
    task = asyncio.create_task(child_func1())

    print("Item 1")

    #add sleep to add a dummy wait
    await asyncio.sleep(2)
    print("Item 2")


async def child_func1():
    print("Price 1")

    #add sleep to add dummy wait for 4 seconds
    await asyncio.sleep(4)
    print("Price 2")

asyncio.run(parent_func())

Output:

Item 1
Price 1
Item 2

If you want your parent asynchronous function to not finish until the child asynchronous functions complete execution, you need to use the await keyword before the child asynchronous function handler.

In the following script, the handler for the asynchronous function child_func1() is assigned to the task variable. Next, at the end of parent_func(), the await keyword is used before the task variable which tells the Python interpreter to wait for the child_func1() to complete its execution. This all sounds complicated but it’s easier to understand when you look at the code below.

This time you’ll see that the child_func1() completes its execution and the string “Price 2” is now printed on the console.

import asyncio

async def parent_func():

    #function to call if current function
    #is waiting for something
    task = asyncio.create_task(child_func1())


    print("Item 1")
    #add sleep to add a dummy wait
    await asyncio.sleep(2)
    print("Item 2")

    #wait for asynchronous function return
    await task

async def child_func1():
    print("Price 1")

    #add sleep to add dummy wait for 4 seconds
    await asyncio.sleep(4)
    print("Price 2")

asyncio.run(parent_func())

Output:

Item 1
Price 1
Item 2
Price 2

Returning Values from Asynchronous Functions

You can also return values from an asynchronous function just like any other function. To do so, you have to use the return keyword inside the asynchronous function. In the calling function, you need to use the await keyword with the function handler for the child asynchronous function which will return the value returned by the asynchronous function.

In the following script, the child_func1() returns a string “Price 3” to the calling function parent_func() which it stores in the value variable and prints on the console.

import asyncio

async def parent_func():

    #function to call if current function
    #is waiting for something
    task = asyncio.create_task(child_func1())


    print("Item 1")
    #add sleep to add a dummy wait
    await asyncio.sleep(2)
    print("item 2")

    #wait for asynchronous function return
    value = await task
    print(value)

async def child_func1():

    print("Price 1")
    print("Price 2")

    return "Price 3"

asyncio.run(parent_func())

Output:

Item 1
Price 1
Price 2
item 2
Price 3

I hope you found this tutorial helpful! Try these scripts and see what you can build. To get a free Python tutorial like this each week, subscribe using the form below.


Want to do more with Python?

We've uncovered a lot more tricks to help you get the most out of Python. To take your Python programming to the next level, enter your email address below and we'll send you our most powerful Python tricks yet.

Yes, show me more free Python tips