Last Updated on February 3, 2023
You can use the async/await pattern in Python to implement asynchronous programming.
In this tutorial, you will discover async/await in Python and exactly what it means and when to use it.
Let’s get started.
What is Async/Await
Async/await refers to a pattern used for asynchronous programming.
In computer programming, the async/await pattern is a syntactic feature of many programming languages that allows an asynchronous, non-blocking function to be structured in a way similar to an ordinary synchronous function
— Async/await, Wikipedia.
Asynchronous programming is a programming paradigm that does not block.
Instead, requests and function calls are issued and executed somehow in the background at some future time. This frees the caller to perform other activities and handle the results of issued calls at a later time when results are available or when the caller is interested.
You can learn more about asynchronous programming in the tutorial:
One way of implementing asynchronous programming in modern programming languages is to use the async/await pattern.
Generally, “async” defines a coroutine, and “await” suspends or yields execution to another coroutine from within a coroutine.
The pattern is used for asynchronous programming in many popular programming languages, such as JavaScript, Swift, Rust, and Python.
Run loops using all CPUs, download your FREE book to learn how.
What is Async/Await in Python
Async/await was introduced in Python version 3.5.
New syntax features: PEP 492, coroutines with async and await syntax.
— What’s New In Python 3.5
It was developed according to PEP 492 which describes how to add coroutines and await/async to Python.
It is proposed to make coroutines a proper standalone concept in Python, and introduce new supporting syntax. The ultimate goal is to help establish a common, easily approachable, mental model of asynchronous programming in Python and make it as close to synchronous programming as possible.
— PEP 492 – Coroutines with async and await syntax
Specifically, this change introduced coroutines as first-class objects or types.
A coroutine is a function that can be suspended and resumed.
It is often defined as a generalized subroutine.
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.
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
You can learn more about coroutines in the tutorial:
It also introduced new expressions for making use of coroutines, collectively referred to as async/await.
PEP 492 greatly improves support for asynchronous programming in Python by adding awaitable objects, coroutine functions, asynchronous iteration, and asynchronous context managers.
— What’s New In Python 3.5
What is the async/await syntax in Python?
What is Async
Async refers to a suite of expressions for working with coroutines.
This includes:
- “async def” for defining a coroutine.
- “async for” for traversing an asynchronous iterable.
- “async with” for using an asynchronous context manager.
The “async def” expression defines a coroutine, but the “async for” and “async with” expressions can only be used within a coroutine, e.g. within an “async def” expression.
Note that both async for and async with can only be used inside a coroutine function declared with async def.
— What’s New In Python 3.5
Let’s take a closer look at each.
The “async def” Expression
A coroutine can be defined via the “async def” expression.
This is an extension of the “def” expression for defining subroutines.
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(): # ... |
A coroutine 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 “async for” and “async with“.
Execution of Python coroutines can be suspended and resumed at many points (see coroutine). await expressions, async for and async with can only be used in the body of a coroutine function.
— Coroutine function definition
You can learn more about defining coroutines in the tutorial:
The “async for” Expression
The “async for” expression is used to traverse an asynchronous iterator.
It is an asynchronous for-loop statement.
An asynchronous iterator is an iterator that yields awaitables.
asynchronous iterator: An object that implements the __aiter__() and __anext__() methods. __anext__ must return an awaitable object. async for resolves the awaitables returned by an asynchronous iterator’s __anext__() method until it raises a StopAsyncIteration exception.
— Python Glossary
The async for expression can be used to traverse an asynchronous iterator within a coroutine.
For example:
1 2 3 4 |
... # traverse an asynchronous iterator async for item in async_iterator: print(item) |
This does not execute the for-loop in parallel. The asyncio is unable to execute more than one coroutine at a time within a Python thread.
Instead, this is an asynchronous for-loop.
The difference is that the coroutine that executes the for-loop will suspend and internally await for each awaitable.
Behind the scenes, this may require coroutines to be scheduled and awaited, or tasks to be awaited.
We may also use the async for expression in a list comprehension.
For example:
1 2 3 |
... # build a list of results results = [item async for item async_iterator] |
This would construct a list of return values from the asynchronous iterator.
You can learn more about the “async for” expression in the tutorial:
The “async with” Expression
The “async with” expression is for creating and using asynchronous context managers.
An asynchronous context manager is a context manager that is able to suspend execution in its enter and exit methods.
— The async with statement
It is an extension of the “with” expression for use in coroutines within asyncio programs.
The “async with” expression is just like the “with” expression used for context managers, except it allows asynchronous context managers to be used within coroutines.
The async with expression allows a coroutine to create and use an asynchronous version of a context manager.
For example:
1 2 3 4 |
... # create and use an asynchronous context manager async with AsyncContextManager() as manager: # ... |
This is equivalent to something like:
1 2 3 4 5 6 7 8 |
... # create or enter the async context manager manager = await AsyncContextManager() try: # ... finally: # close or exit the context manager await manager.close() |
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.
What is Await
Await refers to the “await” expression used with coroutines.
It can only be used within a coroutine and is used to yield execution to an awaitable.
Await expression: Suspend the execution of coroutine on an awaitable object. Can only be used inside a coroutine function.
— Python Expressions
An awaitable may be another coroutine or a coroutine wrapped in a Task object for independent execution.
An object that can be used in an await expression. Can be a coroutine or an object with an __await__() method.
— Python Glossary
Put another way, await will cause the caller coroutine to suspend execution at that point and wait for the given awaitable to be done.
The await expression can be used by using the “await” keyword followed by an awaitable.
For example:
1 2 3 |
... # await a coroutine await custom_coroutine() |
This line does a few things.
Firstly, it creates a coroutine object.
It then schedules the coroutine for execution in the asyncio event loop.
The caller then suspends execution and waits for the new coroutine to be done.
The awaitable coroutine may return a value that we may want after the awaitable is done.
This can be assigned as part of the await expression.
For example:
1 2 3 |
... # await a coroutine and store the return value value = await custom_coroutine() |
You can learn more about the await expression in the tutorial:
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
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 the async/await in Python and exactly what it means and when to use it.
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Stephan Louis on Unsplash
Dan Peterson says
“The pattern is used for asynchronous programming in many popular programming languages, such as JavaScript, Swift, Rust, and Python.”
It is very strange not to mention C#/.NET in this list of languages using async/await given that Microsoft invented it in F# in 2007 and added it to C# 5.0 in 2012. I was at MS BUILD when it was announced, and it was kind of a big deal.
https://en.wikipedia.org/wiki/Async/await
The argument also cannot be made that C# isn’t popular, given that it has more users than Swift and Rust, and comes more highly recommended as a new language for starting a project than all but Python in your list.
https://www.tiobe.com/tiobe-index/
Very odd exclusion.
Jason Brownlee says
Sorry, I have not used MS languages (at least not C# since the first version ~20 years ago). Thanks for the tip.