Uvicorn in Modern Python APIs

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • MyrinNew
    Senior Member
    • Feb 2024
    • 5175

    #1

    Uvicorn in Modern Python APIs

    A quick guide to why Uvicorn is essential for Python developers in 2026, how to use it, and how it stacks up against other languages.


    What is Uvicorn?

    Uvicorn is a high-speed ASGI (Asynchronous Server Gateway Interface) server. While frameworks like FastAPI or Starlette help you write your code, Uvicorn is the "engine" that actually runs the code and handles web requests from users.


    Why do we use it?

    In the past, Python servers (WSGI) could only handle one request at a time per process. Uvicorn uses an asynchronous event loop, allowing it to handle thousands of concurrent connections (like WebSockets or long-polling) without waiting for one to finish before starting the next.


    Quick Start Example

    Install:






    pip install uvicorn







    Code (main.py):






    async def app(scope, receive, send):
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [[b'content-type', b'text/plain']],
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, Dev.to!',
    })







    Run:






    uvicorn main:app --reload







    Alternatives to Consider

    Hypercorn: Great if you need HTTP/3 support.

    Daphne: The go-to for Django Channels.

    Granian: A Rust-based runner for those who need even more speed.

    Architecture Comparison (Python vs. The World)

    How does Uvicorn's "Event Loop" compare to other languages in 2026?




    Perfomance

    Unicorn: ~150k requests/sec; excellent for I/O but limited by the Global Interpreter Lock (GIL).


    Nodejs: ~600k requests/sec; highly optimized for I/O-bound web traffic.

    Go (Goroutines): >1M requests/sec; built-in concurrency makes it a "workhorse" for microservices.

    Rust (Tokio/Axum): >1M requests/sec; the fastest model due to lack of garbage collection and zero-cost abstractions.

    Cpu-intensive tasks

    In a single-threaded async loop, one heavy CPU calculation can freeze the entire server. We should offload blocking tasks to a thread pool or a separate worker (like Celery/Arq) to keep the Uvicorn loop responsive.


    Example: Use run_in_executor for blocking code.






    import asyncio

    @app.get("/heavy-task")
    async def heavy_task():
    # Don't run blocking code directly; offload it to keep the loop free
    loop = asyncio.get_running_loop()
    result = await loop.run_in_executor(None, some_blocking_heavy_math)
    return result







    Summary

    If you are building a modern Python web app, Uvicorn is the standard choice. It balances the ease of Python with the speed required for modern, real-time web applications.


    Follow for more bite-sized dev tutorials! 🚀

    HASH


    refs:

    https://medium.com/@yogeshkrishnanseeniraj/scaling-django-async-workers-uvicorn-gunicorn-celery-and-redis-full-benchmarking-guide-fef057069e96#:~:text=Uvicorn%20alone%20provides%20 excellent%20async,with%20low%20to%20moderate%20tra ffic.

    https://stackoverflow.com/questions/21485920/single-threaded-event-loop-vs-multi-threaded-non-blocking-worker-in-node-js#:~:text=As%20a%20minor%20addendum%20I,57.8k10%2 093%20131






    More...
Working...