Search code examples
pythonflasksocket.iogeventgevent-socketio

gevent-socketio send message from thread


I would like to use gevent-socketio to send messages from a worker thread and update all connected clients on the status of the job.

I tried this:

from flask import Flask, render_template
from flask.ext.socketio import SocketIO, send, emit
import threading
import time

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)

@socketio.on('message')
def handle_message(message):
    send(message, broadcast=True)

@app.route('/')
def index():
    return render_template('index.html')

def ping_thread():
    while True:
        time.sleep(1)
        print 'Pinging'
        send('ping')

if __name__ == '__main__':
    t = threading.Thread(target=ping_thread)
    t.daemon = True
    t.start()
    socketio.run(app)

And it gives me this error:

RuntimeError: working outside of request context

How do I send messages from a function that doesn't have the @socketio.on() decorator? Can I use gevent directly to send messages to socketio?


Solution

  • From this section of the documentation:

    Sometimes the server needs to be the originator of a message. This can be useful to send a notification to clients of an event that originated in the server. The socketio.send() and socketio.emit() methods can be used to broadcast to all connected clients:

    def some_function():
        socketio.emit('some event', {'data': 42})
    

    This emit is not from from flask.ext.socketio import SocketIO, send, but instead called on your socketio variable from socketio = SocketIO(app). Had you done socketio_connection = SocketIO(app), then you'd be calling socketio_connection.emit() to broadcast your data.