Getting started with Async requests in Flask using Httpx

Async requests in Flask using Httpx

Recently Flask has introduced async routes in its 2.0 update. This blog is everything about async requests with Flask 2.0. The Flask 2.0 has come up with many interesting updates. Do check out this blog of Progress Story for all the updates of Flask 2.0. In this blog, we will be going to learn something about asyncio, aiohttp and async routes of Flask.

Agenda

We will be covering the below topics in this blog

Async requests with Asyncio — async/await

Asyncio is a library to write concurrent code using the async/await syntax. It is used as a foundation for multiple Python asynchronous frameworks that provide high-performance network and web servers, database connection libraries, distributed task queues, etc.

It is often a perfect fit for IO-bound and high-level structured network code.

import asyncioasync def main():
print('Hello ...')
await asyncio.sleep(1)
print('... World!')
# Python 3.7+
asyncio.run(main())

Using Python asyncio , we can also make better use of the CPU sitting idle when waiting for the I/O. asyncio is single-process and single-thread. There is an event loop in asyncio , which routinely measure the progress of the tasks.

If the event loop has measured any progress, it would schedule another task for execution, therefore, minimizing the time spent on waiting for I/O. This is also called cooperative multitasking. The tasks must cooperate by announcing when they are ready to be switched out. And the announcement is explicitly made by await keyword.

Async in Flask 2.0

Let’s create a simple Flask application that is having a route that calls some URL and fetches the result synchronously. For that, we would need to install flask and requests a library

pip install flask
pip install requests

To make it interactive we will be using the xkcd comic images. If you haven’t heard about this, then do check out what xkcd comic is.

Now let’s create an API comic that will render a random page of xkcd comic using the requests library

progress story — xkcd comic flask api

Output:

To fetch one page from the comic book it took around 1 sec. Let’s say we want to fetch 5 pages from a comic book, then it will take approximately around 5 secs.

Output

Flask application is fetching 5 images from xkcd comic synchronously. Initially, it fetches the first image and waits for the response and doing nothing at that time. Then once the response is received then it again fetches the second image and doing nothing at that time. This task is an I/O bound task where the CPU is sitting idle doing nothing and waiting for the result of the I/O task, in this case, it is an API call.

This problem can be solved with multithreading and asyncio. In this blog, we will learn how we can solve this using asyncio in Flask. Let’s modify our existing code a bit.

For asyncio to work in the flask, we must satisfy the prerequisites.

pip install "Flask[async]"
pip install httpx

Implementation of async requests

For async routes in flask 2.0 just use the below syntax

@app.get('/comic')
async def hello():
pass

Now we want to call multiple times API but all in an asynchronous fashion. At present, the requests library is not able to do that. So for that, we will install the httpx library and convert the code like below

async def get_multiple_images(number):
async with httpx.AsyncClient() as session: # asynclient will work with async
tasks = [get_xkcd_image(session) for _ in range(number)]
result = await asyncio.gather(*tasks, return_exceptions=True) # will use gather to run every coroutine asynchronously and gather the result in ordered fashion
return result

Convert the API request to a coroutine

async def get_xkcd_image(session):
random = randint(0, 300)
result = await session.get(f'http://xkcd.com/{random}/info.0.json') # create awaitable object of session get so that at this point, thread will not wait for the result instead of it it will do a context switch to other part of program
return result.json()['img']

Put await before the actual call to third party API. By using await it will not wait for the result of the third party API call. Instead, it will do the context switching to other parts of the program.

The new code will look like below.

For the complete blog and implementation, please checkout Async Requests with Flask and Httpx blog on my blogging website — Progress Story

Conclusion

FastAPI/Quart are well known for the async routes frameworks. If you are considering or migrating from flask to these frameworks just for this reason then, I guess it’s time to use Flask to the fullest.

I hope, it has helped you or it will help you. If you want to discuss anything or anything related to tech, you can contact me here or on the Contact Page of Progress Story. If you are interested in becoming a part of the Progress story please reach out to me or check out the Create Blog page.

See you next time! Peace Out ✌️

Creator of progressstory.com blogging website.