The asyncio module in Python provides a low-level and a high-level API.
The low-level API is for library and framework developers, whereas the high-level API builds on top of the low-level API and is intended for application developers.
Nevertheless, the presence and wide use of both APIs make things confusing to those just getting started with asyncio.
In this tutorial, you will discover the two asyncio APIs and which one you should be using.
Let’s get started.
Asyncio APIs
A major problem with asyncio is that it offers two APIs.
It is a problem because beginners get confused about which API to use for their programs.
This confusion leaks out into tutorials, teaching how to get started and use asyncio.
A related issue is that the API has changed a lot in the last 5+ years. The API is stable now, and much simpler.
Nevertheless, earlier versions were more challenging to use, and many (perhaps most) of the examples available on the internet show how to use older versions of the API, which are more difficult and more frustrating to use.
For example, if you see examples getting access to the event loop or have a “loop” variable, you’re probably looking at an example developed using the older version of the API.
What are the two asyncio APIs and which should we use?
Run loops using all CPUs, download your FREE book to learn how.
What are the Two Asyncio APIs?
Asyncio offers two APIs.
They are:
- High-level API for application developers (us)
- Low-level API for framework and library developers (not us)
Let’s take a closer look at what capabilities are provided by each of these APIs.
High-Level Asyncio API
The high-level asyncio API is for application developers.
That is, it is for you and me.
It provides the following capabilities:
- Runners: for starting and running asyncio programs.
- Coroutines and Tasks: for creating, running, and waiting on many coroutines tasks.
- Streams: for socket programming with non-blocking I/O.
- Synchronization Primitives: for synchronizing and coordinating coroutines and coroutine safety.
- Subprocesses: for running commands and managing subprocesses using non-blocking I/O.
- Queues: for sharing data between coroutines in a coroutine-safe manner.
- Exceptions: for various failure conditions in asyncio programs.
You can see a summary of this API here:
Low-Level Asyncio API
The low-level asyncio API is for framework and library developers.
We rarely if ever should be using the low-level asyncio API.
Most activities that can be achieved using the high-level API can also be achieved via the low-level API. When we’re developing asyncio applications, we should try to stick to the high-level API as much as possible, and only adopt the low-level API when there is no alternative.
The low-level API provides the following capabilities:
- Event Loop: for gaining access and interacting directly with the asyncio event loop.
- Futures: for managing the underlying awaitable base type called a future.
- Transports and Protocols: for managing the underlying protocols for network programming.
- Policies: for governing the behavior of asyncio event loops.
- Platform Support: for managing platform-specific event loops and non-blocking implementations.
- Extending: for extending the asyncio in various ways.
You can see a summary of this API here:
Which API Should You Use?
A big problem with beginners is that they use the wrong asyncio API.
This is common for a number of reasons.
- The API has changed a lot with recent versions of Python.
- The API docs page makes things confusing, showing both APIs.
- Examples elsewhere on the web mix up using the different APIs.
Using the wrong API makes things more verbose (e.g. more code), more difficult, and way less understandable.
The lower-level API provides the foundation for the high-level API and includes the internals of the event loop, transport protocols, policies, and more.
… there are low-level APIs for library and framework developers
— asyncio — Asynchronous I/O
We should almost always stick to the high-level API.
We absolutely must stick to the high-level API when getting started.
We may dip into the low-level API to achieve specific outcomes on occasion.
One use case for using the low-level API that I find common is getting control over the thread or process pool used for executing blocking tasks and function calls in asyncio programs.
This requires getting the asyncio event loop and calling the run_in_executor() function.
You can learn more about running blocking calls in asyncio in the tutorial:
You can learn more about interacting with the event loop in the tutorial:
If you start getting a handle on the event loop or use a “loop” variable to do things, you are probably doing it wrong.
I am not saying don’t learn the low-level API.
Go for it. It’s great.
Just don’t start there.
Drive asyncio via the high-level API for a while. Develop some programs. Get comfortable with asynchronous programming and running coroutines at will.
Then later, dip in and have a look around.
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.
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
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Takeaways
You now know about the two asyncio APIs and when to use each.
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Taun Stewart on Unsplash
Do you have any questions?