You can define and run async functions in Python.
An async function in Python is called a coroutine and can be defined via the “async def” expression. Unlike a regular function, it can choose when to suspend its execution using the “await” expression.
In this tutorial, you will discover async functions in Python.
Let’s get started.
What is an Async Function in Python
An async function in Python is a special type of function that is defined using the async keyword before the def keyword.
This is called an “async def” expression.
For example:
1 2 3 |
# define an async function async def custom_work(): # do things... |
You can learn more about the “async def” expression in the tutorial:
Async functions are part of Python’s asynchronous programming model and allows you to write code that can be paused and resumed asynchronously.
Async functions are typically used with the await keyword to pause their execution until an awaited asynchronous operation is completed, such as I/O operations, network requests, or other asynchronous tasks.
For example, an async function can suspend its execution and allow other async functions to run by using the “await” expression and awaiting for another async function, like the asyncio.sleep() async function.
1 2 3 4 |
# define an async function async def custom_work(): # suspend await asyncio.sleep(1) |
You can learn more about the asyncio.sleep() async function in the tutorial:
You can learn more about the “await” expression in the tutorial:
Async functions involve using the “async def” and “await” expressions over and over to define an async program.
This is called the async/await pattern or pattern for asynchronous programming. You can learn more about async/await in the tutorial:
Run loops using all CPUs, download your FREE book to learn how.
Async Functions Are Called Coroutines
An async function is called a coroutine.
Python coroutines are first-class concepts that can be used to develop asynchronous programs.
A coroutine is a function that can be suspended and resumed.
It is often defined as a generalized subroutine.
coroutine: Coroutines are a more generalized form of subroutines. Subroutines are entered at one point and exited at another point. Coroutines can be entered, exited, and resumed at many different points.
— PYTHON GLOSSARY
A subroutine can be executed, starting at one point and finishing at another point. Whereas, a coroutine can be executed then suspended, and resumed many times before finally terminating.
Specifically, coroutines have control over when exactly they suspend their execution.
This may involve the use of a specific expression, such as an “await” expression in Python, like a yield expression in a Python generator.
A coroutine may suspend for many reasons, such as executing another coroutine, e.g. awaiting another task or waiting for some external resources, such as a socket connection or process to return data.
Many coroutines can be created and executed at the same time. They have control over when they will suspend and resume, allowing them to cooperate as to when concurrent tasks are executed.
This is called cooperative multitasking and is different from the multitasking typically used with threads called preemptive multitasking tasking.
You can learn more about Python coroutines in the tutorial:
Async Function vs Sync Function
In Python an “async function” is called a “coroutine” and a “sync function” is called a “function” or a “method” associated with a class.
A function more generally is also known as a “routine” or a “subroutine“.
A sync function or function is a discrete module of expressions that is assigned a name, may take arguments, and may return a value.
- Sync Function: A module of instructions that can be executed on demand, typically named, and may take arguments and return a value. also called a function.
A function is executed, runs through the expressions, and returns somehow. Typically, a function is called by another function.
An async function or coroutine is an extension of a function. This means that a function is a special type of coroutine.
An async function is like a function in many ways, such as:
- They both are discrete named blocks of expressions.
- They both can take arguments, or not.
- They both can return a value, or not.
The main difference is that an async function chooses to suspend and resume its execution many times before returning and exiting.
Both async functions and functions can call other examples of themselves.
- A sync function can call other functions.
- An async function can await other async functions.
The difference is that a sync function cannot run other async functions, but an async function can run other sync functions.
Free Python Asyncio Course
Download your FREE Asyncio PDF cheat sheet and get BONUS access to my free 7-day crash course on the Asyncio API.
Discover how to use the Python asyncio module including how to define, create, and run new coroutines and how to use non-blocking I/O.
How to Use an Async Function in Python
Python provides async functions as coroutines for concurrency.
They are provided in two main ways:
- Through specific additions to the language, e.g. async and await expressions.
- Through a specific module in the standard library, e.g. asyncio module.
Let’s take a tour of how we can create and use async functions in Python.
How to Define an Async Function
An async function can be defined via the “async def” expression.
This is an extension of the “def” expression for defining functions.
It defines a coroutine that can be created and returns a coroutine object.
For example:
1 2 3 |
# define a coroutine async def custom_coro(): # ... |
An async function defined with the “async def” expression is referred to as a “coroutine function”
coroutine function: A function which returns a coroutine object. A coroutine function may be defined with the async def statement, and may contain await, async for, and async with keywords.
— PYTHON GLOSSARY
A coroutine can then use coroutine-specific expressions within it, such as await, async for, and async with.
For example:
1 2 3 4 |
# define a coroutine async def custom_coro(): # await another coroutine await asyncio.sleep(1) |
You can learn more about defining coroutines in the tutorial:
How to Create an Async Function
Once an async function is defined, it can be created.
This looks like calling a function.
For example:
1 2 3 |
... # create a coroutine coro = custom_coro() |
This does not execute the async function.
Instead, it returns a “coroutine” object.
You can think of a coroutine function as a factory for coroutine objects; more directly, remember that calling a coroutine function does not cause any user-written code to execute, but rather just builds and returns a coroutine object.
— PAGE 516, PYTHON IN A NUTSHELL, 2017.
A “coroutine” Python object has methods, such as send() and close(). It is a type.
A coroutine object is an awaitable.
This means it is a Python type that implements the __await__() method.
You can learn more about awaitables in the tutorial:
How to Run an Async Function From Python
An async function can be defined and created, but it can only be executed within an asyncio event loop.
The event loop is the core of every asyncio application. Event loops run asynchronous tasks and callbacks, perform network IO operations, and run subprocesses.
— ASYNCIO EVENT LOOP
The event loop that executes async functions, manages the cooperative multitasking between async functions.
You can learn more about the asyncio event loop in the tutorial:
The typical way to start an asyncio event loop is via the asyncio.run() function.
This function takes one async function and returns the value of the function. The provided async function can be used as the entry point into the asyncio program.
For example:
1 2 3 |
... # start the event loop and run an async function asyncio.run(custom_coro()) |
You learn more about executing async functions in asyncio programs in the tutorial:
Now that we know what async functions are and how to run them, let’s look at a complete example.
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Example Hello World Async Function
The first program we wrote in a new programming language is a “hello world” program.
Therefore, the first step in using async functions in Python is to write a hello world program.
The complete example is listed below.
Type the example and run it.
Or copy-paste it.
This is your first step on the asyncio journey.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# SuperFastPython.com # hello world program for asyncio import asyncio # define a coroutine async def custom_coroutine(): # sleep for a moment await asyncio.sleep(1) # report a message print('Hello world') # execute the coroutine asyncio.run(custom_coroutine()) |
Running the example reports the “hello world” message.
1 |
Hello world |
Did it run okay for you?
Ensure you are using Python 3.7 or higher.
Let’s understand what happened.
The program defines a new async function called custom_coroutine().
The program starts with a call to asyncio.run() and passes it a coroutine object.
The coroutine object was created by calling our newly defined async function called custom_coroutine. This did not execute the custom_coroutine() async function, it just created a “coroutine” type object that can be run by the event loop.
The asyncio.run() method started the asyncio event loop and ran the provided coroutine object.
Our custom_coroutine() async function ran.
First, it called the asyncio.sleep() async function and created another coroutine. It then awaited it via an “await” expression.
This suspends our async function and allows the new asyncio.sleep() coroutine object to run.
Our program sleeps for one second.
The asyncio.sleep() coroutine terminates and our custom_coroutine() async function resumes.
It prints a hello world message and terminates.
The asyncio event loop then closes and the program is done.
This highlights how we can define and execute an async function in Python.
You can learn more about a Hello World asyncio program in the tutorial:
Further Reading
This section provides additional resources that you may find helpful.
Python Asyncio Books
- Python Asyncio Mastery, Jason Brownlee (my book!)
- Python Asyncio Jump-Start, Jason Brownlee.
- Python Asyncio Interview Questions, Jason Brownlee.
- Asyncio Module API Cheat Sheet
I also recommend the following books:
- Python Concurrency with asyncio, Matthew Fowler, 2022.
- Using Asyncio in Python, Caleb Hattingh, 2020.
- asyncio Recipes, Mohamed Mustapha Tahrioui, 2019.
Guides
APIs
- asyncio — Asynchronous I/O
- Asyncio Coroutines and Tasks
- Asyncio Streams
- Asyncio Subprocesses
- Asyncio Queues
- Asyncio Synchronization Primitives
References
Takeaways
You now know how to use async functions in Python.
Did I make a mistake? See a typo?
I’m a simple humble human. Correct me, please!
Do you have any additional tips?
I’d love to hear about them!
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Barbara Rezende on Unsplash
Do you have any questions?