DEV Community

Cover image for 6 Powerful Python Libraries for High-Performance Async Web Development
Aarav Joshi
Aarav Joshi

Posted on

6 Powerful Python Libraries for High-Performance Async Web Development

As a best-selling author, I invite you to explore my books on Amazon. Don't forget to follow me on Medium and show your support. Thank you! Your support means the world!

Python has revolutionized web development with its async capabilities, and I've had the pleasure of working with several powerful libraries that harness this potential. Let me share my experiences and insights on six key libraries that have transformed the landscape of async web development.

FastAPI has quickly become my go-to framework for building high-performance APIs. Its combination of speed, ease of use, and automatic API documentation makes it a standout choice. I've found that FastAPI's use of Python type hints not only improves code readability but also enables automatic request validation and serialization.

Here's a simple example of a FastAPI application:

from fastapi import FastAPI

app = FastAPI()

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

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}
Enter fullscreen mode Exit fullscreen mode

This code sets up a basic API with two endpoints. The type hinting on the item_id parameter automatically validates that it's an integer.

When it comes to both client and server-side async HTTP operations, aiohttp has been my reliable companion. It's a versatile library that I've used for everything from making concurrent API requests to building full-fledged web servers.

Here's an example of using aiohttp as a client to make multiple concurrent requests:

import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = ['http://example.com', 'http://example.org', 'http://example.net']
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        responses = await asyncio.gather(*tasks)
        for url, response in zip(urls, responses):
            print(f"{url}: {len(response)} bytes")

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

This script concurrently fetches content from multiple URLs, demonstrating the power of async operations.

Sanic has impressed me with its Flask-like simplicity combined with asynchronous performance. It's designed to be easy to use for developers familiar with Flask, while still leveraging the full power of async programming.

Here's a basic Sanic application:

from sanic import Sanic
from sanic.response import json

app = Sanic("MyApp")

@app.route("/")
async def test(request):
    return json({"hello": "world"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)
Enter fullscreen mode Exit fullscreen mode

This sets up a simple JSON API endpoint, showcasing Sanic's straightforward syntax.

Tornado has been a reliable choice for me when building scalable, non-blocking web applications. Its integrated networking library makes it particularly useful for long-polling and WebSockets.

Here's an example of a Tornado WebSocket handler:

import tornado.ioloop
import tornado.web
import tornado.websocket

class EchoWebSocket(tornado.websocket.WebSocketHandler):
    def open(self):
        print("WebSocket opened")

    def on_message(self, message):
        self.write_message(u"You said: " + message)

    def on_close(self):
        print("WebSocket closed")

if __name__ == "__main__":
    application = tornado.web.Application([
        (r"/websocket", EchoWebSocket),
    ])
    application.listen(8888)
    tornado.ioloop.IOLoop.current().start()
Enter fullscreen mode Exit fullscreen mode

This code sets up a WebSocket server that echoes back any messages it receives.

Quart has been a game-changer for projects where I needed to migrate Flask applications to async without a complete rewrite. Its API is almost identical to Flask, making the transition smooth and straightforward.

Here's a simple Quart application:

from quart import Quart, websocket

app = Quart(__name__)

@app.route('/')
async def hello():
    return 'Hello, World!'

@app.websocket('/ws')
async def ws():
    while True:
        data = await websocket.receive()
        await websocket.send(f"echo {data}")

if __name__ == '__main__':
    app.run()
Enter fullscreen mode Exit fullscreen mode

This example shows both a standard route and a WebSocket route, demonstrating Quart's versatility.

Starlette has been my foundation of choice when I needed a lightweight ASGI framework. It's the basis for FastAPI, and I've found it excellent for building high-performance async web services.

Here's a basic Starlette application:

from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route

async def homepage(request):
    return JSONResponse({'hello': 'world'})

app = Starlette(debug=True, routes=[
    Route('/', homepage),
])
Enter fullscreen mode Exit fullscreen mode

This sets up a simple JSON API, showcasing Starlette's minimalist approach.

When working with these async libraries, I've learned several best practices that have significantly improved my applications' performance and reliability.

For handling long-running tasks, I've found it crucial to use background tasks or job queues. This prevents these operations from blocking the main event loop. Here's an example using FastAPI's BackgroundTasks:

from fastapi import FastAPI, BackgroundTasks

app = FastAPI()

def write_log(message: str):
    with open("log.txt", mode="a") as log:
        log.write(message)

@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
    background_tasks.add_task(write_log, f"Notification sent to {email}")
    return {"message": "Notification sent in the background"}
Enter fullscreen mode Exit fullscreen mode

This code schedules the log writing to happen in the background, allowing the API to respond immediately.

For database operations, I've learned to use async database drivers whenever possible. Libraries like asyncpg for PostgreSQL and motor for MongoDB have been invaluable. Here's an example using asyncpg:

import asyncpg
import asyncio

async def run():
    conn = await asyncpg.connect(user='user', password='password',
                                 database='database', host='127.0.0.1')
    values = await conn.fetch('''SELECT * FROM mytable''')
    await conn.close()
    return values

result = asyncio.run(run())
print(result)
Enter fullscreen mode Exit fullscreen mode

This code performs a database query asynchronously, preventing it from blocking other operations.

When dealing with external API calls, I've found it essential to use async HTTP clients and to implement proper error handling and retries. Here's an example using aiohttp with retries:

import aiohttp
import asyncio
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
async def fetch_with_retry(session, url):
    async with session.get(url) as response:
        response.raise_for_status()
        return await response.json()

async def main():
    async with aiohttp.ClientSession() as session:
        try:
            data = await fetch_with_retry(session, 'https://api.example.com/data')
            print(data)
        except Exception as e:
            print(f"Failed to fetch data: {e}")

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

This script attempts to fetch data from an API, automatically retrying up to three times with exponential backoff if it fails.

In terms of performance, I've found that FastAPI and Sanic generally offer the best raw performance for simple APIs. However, the choice of framework often depends more on specific project requirements and team familiarity than pure benchmark numbers.

FastAPI shines when you need automatic API documentation and request validation. I've used it extensively for projects where a clear, self-documenting API was a priority.

Aiohttp is my choice when I need more control over the HTTP client or server behavior. Its flexibility has been crucial in projects involving complex networking requirements.

Sanic has been my go-to when I needed Flask-like simplicity with async capabilities. It's been particularly useful for quickly prototyping async web applications.

Tornado's integrated networking library makes it my preferred choice for applications involving WebSockets or long-polling. I've used it successfully in real-time chat applications and live data streaming services.

Quart has been invaluable in projects where I needed to migrate existing Flask applications to async. Its compatibility with Flask extensions has saved significant development time.

Starlette has been my foundation of choice when building custom web frameworks or when I needed a lightweight ASGI server. Its performance and simplicity make it an excellent choice for microservices.

In conclusion, these six libraries have dramatically improved my ability to build efficient, high-performance async web applications in Python. Each has its strengths, and the choice between them often depends on the specific requirements of the project at hand. By leveraging these tools and following async best practices, I've been able to create web applications that can handle high concurrency with ease, providing responsive and scalable solutions for a wide range of web development challenges.


101 Books

101 Books is an AI-driven publishing company co-founded by author Aarav Joshi. By leveraging advanced AI technology, we keep our publishing costs incredibly low—some books are priced as low as $4—making quality knowledge accessible to everyone.

Check out our book Golang Clean Code available on Amazon.

Stay tuned for updates and exciting news. When shopping for books, search for Aarav Joshi to find more of our titles. Use the provided link to enjoy special discounts!

Our Creations

Be sure to check out our creations:

Investor Central | Investor Central Spanish | Investor Central German | Smart Living | Epochs & Echoes | Puzzling Mysteries | Hindutva | Elite Dev | JS Schools


We are on Medium

Tech Koala Insights | Epochs & Echoes World | Investor Central Medium | Puzzling Mysteries Medium | Science & Epochs Medium | Modern Hindutva

Top comments (0)