Python: How to Define and Call Asynchronous Functions

Updated: July 13, 2023 By: Wolf Post a comment

This concise and straight-to-the-point article shows you how to define and call an asynchronous function (async function) in Python (you’ll need Python 3.5 or higher).

Defining an Async Function

In order to define an asynchronous function, just use the async def keyword followed by the function name and parameters. Inside the function body, use the await keyword to suspend the function execution until another asynchronous operation is completed:

async def async_function(arg):
    # statements
    result = await some_async_operation
    # more statements
    return result

Quick example:

import asyncio

async def say_hello():
    # Mimic an asynchronous action
    await asyncio.sleep(3)

    print("Hello!")

Ways to Call an Async Function

There are several ways to call async functions, but they all have one thing in common: you need to use an event loop, which is an object that manages the execution of asynchronous tasks.

Using asyncio.run()

You can use the asyncio.run() function, which creates an event loop and runs your defined async function until it completes and returns the result.

Example:

import asyncio

# define an asynchronous function
async def return_some_text():
    await asyncio.sleep(3)
    return "some text"

# call the function using asyncio.run()
text = asyncio.run(return_some_text())
print(text)

When executing the code above, you will see the following output after some seconds:

some text

This is a convenient approach to run an async function as a script.

Using asyncio.Runner()

An asyncio.Runner() context manager is a new feature in Python 3.11 that simplifies running multiple async functions in the same context. We can use it with the with statement (this can help us automatically close the event loop when the job is done) like so:

import asyncio

async def first():
  await asyncio.sleep(2)
  print("Welcome to Sling Academy!")

async def second():
  await asyncio.sleep(2)
  print("To the Moon!")

with asyncio.Runner() as runner:
  runner.run(first())
  runner.run(second())

Output (there will be a lag before each message appears):

Welcome to Sling Academy!
To the Moon!

Using asyncio.get_event_loop()

You can use the asyncio.get_event_loop() function to initialize an event loop object, then call the run_until_complete() method. (pass your async function as its argument) on that object like so:

import asyncio

# create an event loop
loop = asyncio.get_event_loop()

# run an asynchronous function until it returns a result
result = loop.run_until_complete(async_function(arg))

# close the event loop
loop.close()

The close() method is used to close the event loop when it is no longer necessary. An event loop may hold some resources that need to be released, such as file descriptors, sockets, threads, or subprocesses. Closing it ensures that those resources are properly cleaned up and avoids memory leaks or resource exhaustion.

And here is a practical example (it does the same thing as the other examples in this article: printing some text asynchronously):

import asyncio

# define an asynchronous function
async def say_after(delay, message):
    # wait for the delay using asyncio.sleep, which is an asynchronous function
    await asyncio.sleep(delay)
    # print the message
    print(message)

# create an event loop
loop = asyncio.get_event_loop()

# run the asynchronous function with some arguments
loop.run_until_complete(say_after(1, "Welcome to Sling Academy!"))
                    
# close the event loop
loop.close()

Output:

Welcome to Sling Academy!

That’s it. This tutorial ends here. Happy coding & have a nice day!