Hello, first thanks for the great library, it's really helped me out. I've been trying to get socketio.emit() working in a thread I've created using socketio.start_background_task(). I am forcing eventlet as the async_mode. SocketIO appears to register the emit, but no data is sent out by EngineIO afterwards.
Here's the difference between somewhere I'm calling emit() inside a decorated handler:

And somewhere I'm using socketio.emit():

Having a super hard time trying to figure this one out. I am also monkey-patching the std lib with eventlet, and both of the worker threads I have should be sleeping sufficiently (the one where I'm calling the emit from is using a Queue).
Edit: Forgot to mention, I'm not seeing this on the client either which is really what my goal is.
Do you have your code somewhere I can see it?
@miguelgrinberg Not at the moment, I was hoping it would be something obvious I was doing wrong. I'll see if I can put together a minimal reproduction of the problem in a gist and post it here, hopefully this weekend.
I am also running into this same exact issue. @zbuttram if you set async_mode=threading in your app, it will fix this issue, but that's not really a viable solution. @miguelgrinberg I will post code later tonight or tomorrow showing a minified app suffering from this issue. It has to do with trying to use socketio.emit outside of the application context.
Here is a sample application. I basically want to be able to emit socketio events directly from server generated events.
server.py
from threading import Thread
from flask import Flask, render_template
from flask_socketio import SocketIO, send, emit, join_room, leave_room
import time
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
# The below line works, but is not what I want. I need to use eventlet
# socketio = SocketIO(app, async_mode='threading')
@app.route('/')
def index():
return render_template('index.html')
@socketio.on('connect', namespace='/hello')
def sys_connect():
print 'client connected'
@socketio.on('join', namespace='/hello')
def join(message):
join_room(message['room'])
print 'client joined room %s' % message['room']
@socketio.on('queues_latest', namespace='/hello')
def latest_queues():
print 'client requested latest queues data'
emit('queues_data_push', {'data':'got the queues!'})
def emit_queues():
data = {'data':'got the queues 2!'}
socketio.emit('queues_data_push', data, namespace='/hello', room='queues')
# The below does not work either. Sometimes I get a Keyerror: current_app.extensions['socketio']
# with app.app_context():
# emit('queues_data_push', data, namespace='/hello', room='queues')
def start_scheduler():
def scheduler_loop():
while True:
time.sleep(5)
emit_queues()
thready = Thread(target=scheduler_loop)
thready.daemon = True
thready.start()
if __name__ == '__main__':
start_scheduler()
socketio.run(app)
client.html
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
</head>
<body>
<ul id="messages"></ul>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io('localhost:5000/hello');
socket.on('connect', function(){
console.log('connection made');
socket.emit('join', {'room':'queues'});
socket.emit('queues_latest');
});
socket.on('queues_data_push', function(msg){
$('#messages').append($('<li>').text(msg.data));
});
</script>
</body>
</html>
Thanks for putting that together @audrummer15, I just couldn't find the time unfortunately. 馃槥
You've hit the nail on the head though, this is exactly what I'm experiencing too. In theory I would be fine with the threading async as a temporary workaround but it doesn't seem to allow actual sockets to work, the clients just use the HTTP polling method of communication and never upgrade to sockets which as you said, precludes it from really being a viable solution.
@audrummer15 Add the following as lines 1 & 2 of your server.py and then your example application works as expected:
import eventlet
eventlet.monkey_patch()
@zbuttram you said you did monkey patch though, so either you didn't do it correctly, or you are seeing a different problem.
@miguelgrinberg that's correct, I'm doing it at the top of my server.py. I'm fairly certain the only difference between @audrummer15's code and mine is that I am doing from server import socketio in another file where my worker thread is. From what I read in the eventlet documentation I shouldn't have to monkey patch in both files, right?
I also took a look at the recent commit history though and it looks like you may have fixed something with emit since I originally posted? If so, it's possible I just need to try my code again with the latest version.
Monkey patching is done only once, in the main script, before anything else is imported.
I have since restructured my project to no longer need the Python-based server I was creating so I'll go ahead and close this issue. I believe it may have been fixed anyway. :)
Most helpful comment
@audrummer15 Add the following as lines 1 & 2 of your server.py and then your example application works as expected:
@zbuttram you said you did monkey patch though, so either you didn't do it correctly, or you are seeing a different problem.