Granian
Granian is a high-performance HTTP server for Python applications, implemented in Rust and built upon the Hyper crate. It supports ASGI/3, RSGI, and WSGI interfaces, offering robust handling for HTTP/1, HTTP/2, and Websockets. The project aims to provide a single, performant dependency solution, avoiding the typical Gunicorn + Uvicorn + http-tools stack. It is actively maintained with regular patch and minor releases, compatible with Python 3.10 and above.
Warnings
- breaking Granian dropped support for Python 3.9 and PyPy 3.9/3.10 starting from v2.6.0. Users on these versions must upgrade their Python environment to Python 3.10 or newer.
- gotcha Prior to v2.7.1, ASGI applications, particularly those using Django channels, might not reliably receive `websocket.disconnect` events after a server-initiated close, potentially leading to connection hangs.
- gotcha Versions prior to v2.7.1 could experience an occasional runtime thread panic (`Cannot drop pointer into Python heap without the thread being attached`) during websocket cleanup on shutdown.
- gotcha On WSGI applications, versions prior to v2.5.6 could have incorrect `PATH_INFO` values in the `environ` dictionary when the `--url-path-prefix` option was used. This could lead to incorrect routing or resource access.
- gotcha On Unix systems, Granian v2.5.5 addressed an issue preventing startup on Python 3.14 when using the `forkserver` multiprocessing start method, by falling back to `spawn`.
Install
-
pip install granian
Imports
- Server
from granian.server.embed import Server
Quickstart
# main.py
async def app(scope, receive, send):
assert scope['type'] == 'http'
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
[b'content-type', b'text/plain'],
],
})
await send({
'type': 'http.response.body',
'body': b'Hello, world!',
})
# To run from your terminal (assuming main.py is in current directory):
# granian --interface asgi main:app --port 8000