Async/Await of Python with Fast API

Table of contents

No heading

No headings in the article.

Python's async/await syntax, introduced in Python 3.5, simplifies the creation of asynchronous code by allowing non-blocking code execution that can perform multiple tasks concurrently without the need for callbacks or threads. FastAPI, a popular web framework for building APIs in Python, leverages async/await heavily to achieve high performance and scalability.

Async/await involves creating and running coroutines that can be paused and resumed, permitting other code to run in between. The event loop can execute other coroutines waiting for I/O operations or other tasks while a coroutine is paused. For instance, the following example showcases a coroutine that employs async/await syntax:

async def my_coroutine():
    print("Starting coroutine")
    await asyncio.sleep(1)
    print("Coroutine resumed")

The async keyword declares my_coroutine as a coroutine function, while await pauses the coroutine and waits for another coroutine or Future to finish. In the example, asyncio.sleep pauses the coroutine for one second.

To run the coroutine, we require an event loop. Here's an example of how to execute my_coroutine with the asyncio event loop:

import asyncio

async def main():
    coro = my_coroutine()
    await coro

asyncio.run(main())

In this example, main is another coroutine that creates an instance of my_coroutine and then awaits it. We can execute the main coroutine using the default event loop with asyncio.run.

FastAPI enables us to define asynchronous endpoints easily with the async def syntax. The Starlette web framework, upon which FastAPI is built, utilizes async/await extensively to achieve high performance and scalability. For instance, the following example defines a FastAPI app with a single asynchronous endpoint that returns a JSON message:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

In this example, the async keyword denotes that root is a coroutine that can be paused and resumed. We can run the app using the uvicorn server:

$ uvicorn main:app --reload

When we send a request to http://localhost:8000/, FastAPI runs the root coroutine and returns the JSON message.

We can perform I/O operations asynchronously within our endpoints using async/await, such as making an asynchronous HTTP request to another API. Here's an example of how to do that in FastAPI:

import httpx

@app.get("/async")
async def async_endpoint():
    async with httpx.AsyncClient() as client:
        response = await client.get("https://example.com")
    return {"message": response.text}

In this example, async_endpoint is another endpoint that makes an asynchronous HTTP request to https://example.com using httpx.