Hi,
I'm trying without success to execute the server as a background thread, and emit event from main thread or other thread.
I have tried two approaches:
Using sio.start_background_task
import json
from flask import Flask
from flask_socketio import SocketIO, emit
app = Flask(__name__)
sio = SocketIO(app)
@sio.on("connect", namespace="/")
def connect():
emit("server_status", "server_up")
print("connect ")
@sio.on("message", namespace="/")
def message(data):
print("message ", data)
@sio.on("disconnect", namespace="/")
def disconnect():
print('disconnect ')
class MapTool(object):
def __init__(self):
self.thread = None
def start_server(self):
print 'starting map server'
sio.run(app, port=8000, debug=True, use_reloader=False)
def start(self):
self.thread = sio.start_background_task(self.start_server)
def send_msg(self, type, data):
print "send_msg"
sio.emit(type, json.dumps(data),namespace="/")
def wait(self):
self.thread.join()
if __name__ == "__main__":
maptool = MapTool()
maptool.start()
import time
while True:
time.sleep(15)
maptool.send_msg("server_status", "test")
maptool.wait()
````
when doing this, I don't receive the connect notification from client.
it looks like the receiving thread is blocked or something.
**Using python thread**
```python
class MapTool(object):
def __init__(self):
self.thread = None
def start_server(self):
"""thread worker function"""
print 'starting map server'
sio.run(app, port=8000, debug=True, use_reloader=False)
def start(self):
self.thread = Thread(target=self.start_server)
self.thread.start()
def send_msg(self, type, data):
print 'send_msg'
sio.emit(type, json.dumps(data),namespace='/')
def wait(self):
self.thread.join()
this way I'm getting a connect notification from the client, but the client is not getting the message emitted.
there is no exception on the server side when emitting the event.
using this setup:
Python - 2.7.9
Flask - 1.0.2
Flask-SocketIO - 3.1.2
gevent - 1.2.2
socketio - 0.1.6
eventlet - 0.24.1
What is the correct way to execute both server (in a background thread) and client in the same process?
First, a little inconsistency in your requirements. Use gevent or eventlet, there is no need to have both installed. I normally prefer eventlet, because it comes with websocket support.
From the two options, the only one that is valid is the first. The second option uses Python threads, which are incompatible with eventlet's threading model. The second option would only have a chance to work if you monkey patch the python standard library so that it becomes compatible with eventlet.
I tried your first option and can confirm that I see the same problem. I'll investigate a bit more and get back to you.
@benizri-ofir this is actually a bug in your application. You are calling time.sleep() which is a blocking call under eventlet. This call is preventing any other tasks in your application from running, including the Socket.IO server and Flask.
Replace that with sio.sleep() or eventlet.sleep(), or else monkey patch the python standard library and then you can use time.sleep().
Most helpful comment
@benizri-ofir this is actually a bug in your application. You are calling
time.sleep()which is a blocking call under eventlet. This call is preventing any other tasks in your application from running, including the Socket.IO server and Flask.Replace that with
sio.sleep()oreventlet.sleep(), or else monkey patch the python standard library and then you can usetime.sleep().