[Python] A Journey to Python Async - 1. Intro
Tags: webdev, python, network
Published: 2023-07-10 01:32:10

**Disclaimer**: this series of articles are not intended to provide full information about async APIs in Python;  it only tries to show the logical flow of understanding the async features in Python from the ground up. Hence I won’t deal with explaining details or a list of available APIs or syntaxes (such as async with, or async for).

## Why I had(and have) to know Async?

### It was JavaScript, just like other developers did.
Ever since I started my career as a software engineer, the jargon “async” has been relentlessly showing up all the time. You’ll be in my shoes especially if you were a web developer. In JavaScript/Node.js, for example, you can’t write even a single application without using `async… await…` syntax. It is not only the case of JS though - you can see everywhere nowadays like C#, Rust, and Python.

But whereas I took for granted that `async` syntax in JS, `async` in Python was quite unfamiliar to me when I saw it for the first time. I had some experiences of using Python for writing really simple scripts, without ever worrying about those async features. That was probably because many big popular libraries such as [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), or even [selenium](https://selenium-python.readthedocs.io/) didn’t require any async logics to be considered. And those libraries were(and still are) the main reasons for using Python at all. 

### Why I want to know about Async in Python?
However, after I joined the current company and started using [FastAPI](https://fastapi.tiangolo.com/), I had to use that `async` feature in Python, although I didn’t really need to understand what those syntaxes meant - I only guessed that they’re acting pretty much like the ones in JS/Node.js. That was quite correct, and everything works just fine. 

But as I got to know more about Python and try to dig deeper inside, it became unavoidable to understand how it works internally - especially if you’re interested in advanced features such as parallel computing and concurrent programming. As an aspiring engineer who wants to create my own things, I got to know about this `async` things in Python. 

## About this series of articles
I never thought this topic has grown to become a series of articles. The more I got to know about the asynchronous features in Python, I had to take into account essentially related parts all together. 

### Coroutine and Generator
Basically, all my questions began with this `async def` syntax, which produces a “coroutine” object. But what is a coroutine? Of course it is a programming pattern, I know it. And it doesn’t exist only in Python as well. But even though I had heard of it a lot, I really wanted to see how it is actually implemented - I really didn’t want to read a single Wikipedia page and forget about actual code. 

But that meant I had to search for related concepts, which boiled down to generators. But generator itself was not an easy concept at all. However, it is a core concept for understanding the coroutine objects, so I had no choice but to investigate this feature as well. 

### (Native)Coroutine and Asyncio library
Figuring out what a coroutine is wasn’t the end of the story. It turned out that it is merely an interface and the details should be filled in by programmers. One of such examples is the [asyncio library](https://docs.python.org/3/library/asyncio.html). It uses the behavior of coroutine objects to implement its own asynchronous API features. At this stage, I delve into the essential features of the library such as event loop, future, and task. 

### The Contents of the Series
So overall, the series would be like this:
- Generator as an Iterator
- Generator as a Coroutine
- Native Coroutine
- Asyncio Features - Event Loop
- Asyncio Features - Task and Future

## Recommended Materials
Perhaps it was my lack of skill in searching for materials on the Internet, but many of them didn’t provide the information I wanted - very few of them went into details, and many things were just showing “how it works” with toy code examples. This is another reason why it took so long a time for me to figure out how that async things work in Python. 

However, I am not saying that there aren’t any good materials out there. I would like to recommend the following list of materials, if you are interested in this topic. Perhaps you don’t even really need to have a look at this series at all!

1. For those who barely know about async things at all, I highly recommend reading through the [tutorial in the FastAPI documentation](https://fastapi.tiangolo.com/async/). It is very intuitive and easy to understand. If you want more of coding, perhaps you would like the [trio tutorial](https://trio.readthedocs.io/en/stable/tutorial.html). Although we won’t cover the trio library in this series, the high level features of any async libraries are almost identical so you can get a brief grasp of how async features are actually written in Python from this tutorial. 

2. If you already have some experiences in using those async features in Python(or in JS), I recommend reading through some books about this topic. One of my favorite [Dead Simple Python](https://www.amazon.com/Dead-Simple-Python-Idiomatic-Programmers/dp/1718500920) or the “bible” [Fluent Python](https://www.amazon.com/Fluent-Python-Concise-Effective-Programming/dp/1492056359) would be a good read. I personally think “dead simple” would be easier, but I find “fluent” is also very clear and easy to understand with many real-world examples. 

3. To understand the internal structure of the asyncio library, it was really helpful for me to read this article: [“500 Lines or Less:  A Web Crawler With asyncio Coroutines”](https://aosabook.org/en/500L/a-web-crawler-with-asyncio-coroutines.html). I happened to discover this article while browsing the CPython documentation. It goes deep into how a generator works and how it relates to the coroutine concepts. Moreover, it also shows some low-level features such as selectors and futures, which really inspired me to look into the actual source code of the asyncio library. Although it is a bit old article, but still, I find it really interesting to read. 

4. Another good read for the general structure of the asyncio library is the [series created by an engineer who participated in a BBC cloud project](https://bbc.github.io/cloudfit-public-docs/asyncio/asyncio-part-1.html). It outlines the overall big picture of the asyncio features, and it really helped me to understand how those features work together in seamless ways. 

5. To understand the relationship between generators and coroutines, reading [this article by one of the main contributors of CPython](https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/) or [a supplement of Fluent Python](https://www.fluentpython.com/extra/classic-coroutines/) will clarify what a classic coroutine is. 

## Conclusion
It will be a long journey, although I never expected it to be like this. There would be some missing things I decided not to cover, but I will try to include essential parts as much as I can.