Python web applications require protocols to communicate between web servers and application code. WSGI (Web Server Gateway Interface) and ASGI (Asynchronous Server Gateway Interface) are two such protocols, each with distinct characteristics and use cases.
WSGI: Synchronous Web Applications
WSGI is the traditional protocol for Python web applications, introduced
in
Core Concepts
- Single callable function (application object)
- Synchronous request-response cycle
- Compatible with most traditional web frameworks
Example WSGI Application
# wsgi_app.py
def simple_wsgi_app(environ, start_response):
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
return [b"Hello from WSGI!"]
# Test the WSGI app
def mock_start_response(status, headers):
print(f"Status: {status}")
print(f"Headers: {headers}")
response = simple_wsgi_app({}, mock_start_response)
print(response[0].decode())
gunicorn --workers=2 --bind 127.0.0.1:8000 wsgi_app:simple_wsgi_app
ASGI: Modern Async Applications
ASGI is a separate asynchronous interface designed as a successor to WSGI.
Its protocol specifications cover
Key Features
- Async-first design
- WebSocket support
- HTTP/2 compatibility
- Better handling of long-lived connections
Example ASGI Application
# asgi_app.py
import asyncio
async def simple_asgi_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 from ASGI!",
})
# Test the ASGI app
responses = []
async def mock_send(message):
responses.append(message)
async def main():
await simple_asgi_app({'type': 'http'}, None, mock_send)
print(f"Status: {responses[0]['status']}")
print(responses[1]['body'].decode())
if __name__ == '__main__':
asyncio.run(main())
uvicorn asgi_app:simple_asgi_app --lifespan off
When to Use Each
WSGI:
- Simple request-response applications
- Legacy systems integration
- Applications built around synchronous libraries
ASGI:
- Real-time applications
- WebSocket requirements
- High-concurrency needs
I/O-boundfluidattacks.github.ioaioextensions documentation, at its explanation of I/O-bound tasks and why asyncio speeds them up. applications
Performance Considerations
- ASGI can overlap
I/OInput/Output efficiently when the application uses nonblocking libraries. - Blocking calls inside an async handler block its
event-loopA loop that waits for events, such as finished I/O, and runs the callback registered for each one. thread unless offloaded. - CPU-bound work needs an appropriate execution strategy with either interface, such as worker processes. Benchmark the actual application and server settings.
The following timeline is an idealized example with two synchronous WSGI workers, nonblocking database calls for ASGI, and no scheduling overhead; it is not a benchmark of the interfaces.