Async and Await in Python: An Introduction

python programs

Summary: In this tutorial, you will learn about async and await in Python and will also learn how to write asynchronous function in Python.

What is Asynchronous Function?

An asynchronous function is a function that can be paused at certain points and resumed later, allowing other tasks to be run in the meantime.

Asynchronous functions are often used to perform I/O-bound or high-latency operations, such as network requests or reading from a file, as they allow other tasks to be run while waiting for the operation to complete.

In Python, asynchronous functions are defined using the async def syntax, and they can contain asynchronous operations using the await keyword.

Asynchronous functions must be called using await or using the asyncio.run() function to execute them. They cannot be called using the regular () syntax.

Here’s an example of an asynchronous function in Python:

import asyncio

async def my_function():
    # asynchronous code here
    await asyncio.sleep(1)
    return 42

This function can be called using await my_function(), which will pause the execution of the calling function for 1 second before returning the value 42.

async and await in Python

The async and await keywords are used to define asynchronous functions and to perform asynchronous operations within those functions, respectively.

They are part of the asyncio library, which is a library for writing asynchronous code using the async/await syntax in Python.

The async keyword is used to define a function as asynchronous.

The await keyword is used to perform asynchronous operations within an asynchronous function. It waits for the result of an asynchronous operation before continuing the execution of the function.

Here is a simple example of using the async and await keywords in Python to perform an asynchronous operation:

import asyncio

async def perform_async_operation():
    # Perform some asynchronous operation here
    await asyncio.sleep(1)  # This line "awaits" for the asyncio.sleep() operation to complete
    print("Async operation complete!")

# Now we can use the async def function like a regular function, but it will execute asynchronously:
async def main():
    await perform_async_operation()

# This will run the main() function in an asyncio event loop
asyncio.run(main())

In this example, the perform_async_operation() function is an async function that performs an asynchronous operation (in this case, waiting for 1 second using asyncio.sleep()) and then prints a message.

The main() function is also an async function that calls perform_async_operation() and waits for it to complete using the await keyword.

Finally, the asyncio.run() function is used to run the main() function in an asyncio event loop.

What is asyncio.run()?

asyncio.run() is a utility function introduced in Python 3.7 for running asynchronous code using the asyncio library. It creates a new event loop, sets it as the current event loop, and runs the provided asynchronous function.

For example, you can use asyncio.run() to run an asynchronous function like this:

import asyncio

async def my_function():
    # asynchronous code here

asyncio.run(my_function())

You can also use asyncio.run() to run multiple asynchronous functions concurrently using the asyncio.gather() function:

import asyncio

async def function_1():
    # asynchronous code here

async def function_2():
    # asynchronous code here

asyncio.run(asyncio.gather(function_1(), function_2()))

asyncio.run() is a convenient way to run asynchronous code, as it handles the creation and management of the event loop for you.

However, it should only be used when you are not already running within an event loop, as it will create a new event loop and set it as the current event loop, which can cause problems if you are already running within a different event loop.

Can’t we use ‘await main()’ to run the program?

The await main() statement runs the main function and waits for it to complete before continuing the execution of the program.

In order to use the await keyword, the code needs to be running inside an event loop, which is responsible for executing asynchronous functions and “waiting” for their results.

The event loop can be started using the asyncio.run() function, which runs the provided asynchronous function and waits for it to complete before returning.

For example, the following code will run the main function asynchronously and wait for it to complete before exiting:

import asyncio

async def main():
    # asynchronous code goes here

asyncio.run(main())

Alternatively, you can use the await keyword inside an asynchronous function that is being run by an event loop. For example:

import asyncio

async def main():
    # asynchronous code goes here

async def wrapper():
    await main()

asyncio.run(wrapper())

In this case, the event loop will run the wrapper function and wait for it to complete, and the wrapper function will in turn run the main function and wait for it to complete.

When to use async and await?

The async and await keywords are used to write asynchronous code in Python using the asyncio library.

Asynchronous code can be useful in a variety of situations, such as when performing I/O-bound or high-latency operations, as it allows other operations to be run in the meantime.

For example, you might use asynchronous code to perform a network request asynchronously, so that the program can continue to run other tasks while waiting for the request to complete.

You might also use asynchronous code to perform a long-running computation in the background, so that the program can continue to run other tasks while the computation is being performed.

In general, you should consider using asynchronous code whenever you have a task that could potentially block the execution of your program for a significant amount of time, and you want to allow other tasks to be run in the meantime.

Here’s an example of an asynchronous function that asynchronously reads a file line by line and prints the lines to the console:

import asyncio

async def print_lines(filename):
    with open(filename, 'r') as f:
        while True:
            line = await f.readline()
            if not line:
                break
            print(line.strip())

asyncio.run(print_lines('myfile.txt'))

This function uses the await keyword to asynchronously read lines from the file, and it uses a while loop to continue reading lines until the end of the file is reached.

You can also use the asyncio library to execute this function concurrently with other asynchronous functions. For example:

import asyncio

async def print_lines(filename):
    with open(filename, 'r') as f:
        while True:
            line = await f.readline()
            if not line:
                break
            print(line.strip())

async def main():
    await asyncio.gather(print_lines('file1.txt'), print_lines('file2.txt'))

asyncio.run(main())

This will execute the print_lines function concurrently for both file1.txt and file2.txt.

Leave a Reply

Your email address will not be published. Required fields are marked *