Flask-SocketIO
Flask-SocketIO is a Flask extension that enables real-time bidirectional communication between clients and servers using the Socket.IO protocol. It provides features like event-based communication, rooms for grouping clients, namespaces for organization, and automatic reconnection. The library is actively maintained, with frequent releases, and its current version is 5.6.1.
Warnings
- breaking Flask-SocketIO 5.x adopted backwards-incompatible changes in the Socket.IO protocol (Socket.IO v3+). This requires the client-side Socket.IO JavaScript library to also be upgraded to a compatible version (e.g., 3.x or 4.x). Mismatched protocol versions will result in connection failures and '400' errors.
- gotcha For production deployments, `socketio.run(app)` should always be used to start the server instead of `app.run()`. `socketio.run()` ensures that an appropriate asynchronous web server (like Eventlet or Gevent, if installed) is used, which is necessary for proper WebSocket functionality and performance. Using `app.run()` will default to Flask's built-in development server, which lacks robust WebSocket support and is not suitable for production.
- gotcha Asynchronous workers (like `gevent` or `eventlet`) are crucial for performance and proper WebSocket handling in production environments. Without them, Flask-SocketIO defaults to Python's threading, which can lead to performance bottlenecks and unresponsiveness under high load. `gevent` is generally preferred over `eventlet` as `eventlet` is in maintenance mode.
- breaking When running multiple Flask-SocketIO server instances behind a load balancer (for scaling), a message queue (such as Redis or RabbitMQ) is mandatory for coordinating operations like broadcasting and rooms. Without a message queue, events will only be delivered to clients connected to the specific server instance that emitted the event. Additionally, the load balancer *must* be configured for 'sticky sessions' to ensure a client's requests are always routed to the same worker.
- gotcha Modifications to the Flask `session` object within SocketIO event handlers create a 'fork' of the session that is independent of the session seen by regular HTTP routes. Changes made in a SocketIO handler will persist for subsequent SocketIO handlers on the same connection but will *not* be visible to Flask HTTP route handlers (and vice-versa). This is due to how sessions are saved, requiring HTTP request/response cycles that don't exist in a SocketIO connection.
- gotcha Blocking operations (e.g., long database queries, heavy computations, network calls) within SocketIO event handlers will block the entire server process when using an asynchronous framework like Gevent or Eventlet, leading to severe performance issues and unresponsiveness.
Install
-
pip install Flask-SocketIO -
pip install Flask-SocketIO[eventlet] -
pip install Flask-SocketIO[gevent] -
pip install Flask-SocketIO redis
Imports
- SocketIO
from flask_socketio import SocketIO
- send
from flask_socketio import send
- emit
from flask_socketio import emit
Quickstart
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'my_secret_key'
socketio = SocketIO(app)
@app.route('/')
def index():
return render_template('index.html')
@socketio.on('my event')
def handle_my_custom_event(json):
print('received json: ' + str(json)) # Logs to server console
emit('my response', json) # Sends a response back to the client that sent it
@socketio.on('message')
def handle_message(message):
print('received message: ' + message)
emit('my response', {'data': message}, broadcast=True) # Broadcasts to all connected clients
if __name__ == '__main__':
# For development, socketio.run() replaces app.run()
# For production, install eventlet or gevent for async workers
socketio.run(app, debug=True)