Quick notes on Python asyncio¶
This post focus on Python asynchronous execution model. Code shown in examples requires Python 3.7+ to work. Over the last few years, asynchronous programming has become an important paradigm and an effective tool for programmer to handle distributed computing.
Asynchronous Programming¶
The idea behind asynchronous execution is not new and fairly intuitive. For an example, imagine you are building a lightweight web server that helps a popular restaurant handle online ordering and many customers might use it at the same time. For a sequential execution model the server will have to wait for each customer to finish the order before it can handle the next request. With sync execution model, the server can launch an hanlder for one customer and immediately returns back to the main loop to find out if there are more pending request while that customer is browsing the menu. After that customer has finished his order, he will inform the server by pressing an confirm button, which brings back your program to process the order. In Python, the above workflow can be roughly described by following snippet:
async accept_request(request):
order = await wait_for_customer(request)
handle_order(order)
In the example, await
means the function should pass the control back to caller until
wait_for_customer
has returned. To use the Python keyword await
one must specify
the function as async
.
Python Asynchronous Programming Basic¶
Quoting from the official document, a simplest example is shown below:
import asyncio
async def main():
print("Hello")
await asyncio.sleep(1)
print("World")
asyncio.run(main())
There’s a lot of things going on in this example, let’s walk them through. First we
import the asyncio
module, which is a builtin module of Python standard library and
provides basic facilities for asynchronous programming. Next the main
function is
prefixed by a keyword async
. Function like this is called Coroutine
. Calling
coroutine doesn’t return the actual result. To obtain the result (including side effect),
one must use some other mechanisms like asyncio.run
. We might want to do a bit more
than just calling 1 function, async
functions can be chained:
import asyncio
async def handle_request(request: int):
asyncio.sleep(request)
async def main():
for re in [1, 3, 5, 7, 9]:
await handle_request(re)
asyncio.run(main())