Python - Flask-SocketIO send message from thread: not always working Python - Flask-SocketIO send message from thread: not always working multithreading multithreading

Python - Flask-SocketIO send message from thread: not always working


I managed to resolve the issue by monkeypatching several Python functions which causes Python to use the eventlet functions instead of the native ones. This way background threads work fine with eventlet.

https://github.com/miguelgrinberg/Flask-SocketIO/blob/e024b7ec9db4837196d8a46ad1cb82bc1e15f1f3/example/app.py#L30-L31


I have the same problem.But I think I found out what's matter.

When starting SocketIO with the following code and create the threading like yours, the client CAN NOT receive the message which emitted by server.

socketio = SocketIO(app)socketio.run()

I find out that the flask_socketio offer a function named start_background_task from document.

Here are the description of it.

start_background_task(target, *args, **kwargs)

Start a background task using the appropriate async model. This is a utility function that applications can use to start a background task using the method that is compatible with the selected async mode.

Parameters:

target – the target function to execute. args – arguments to pass to the function. kwargs – keyword arguments to pass to the function. This function returns an object compatible with the Thread class in the Python standard library.

The start() method on this object is already called by this function.

So I replace my code thread=threading(target=xxx) with socketio.start_background_task(target=xxx) then socketio.run() . The server get stuck in the thread when run into it ,which means that the function start_background_task only returned after the thread finished.

Then I try to use gunicorn to run my server with gunicorn --worker-class eventlet -w 1 web:app -b 127.0.0.1:5000

Then everything works well!

So let start_background_task choose a proper way to start a thread.


The problem that you are running into is caused by the fact that eventlet and gevent (two threading modes of socket.io) don't support multiprocessing. So this is not a bug, but the way that is implemented. In order to make it work you can use async_mode=threading, or you can monkey-patch evenlet to enable the usage of a background thread.

socketio = SocketIO(app, async_mode='eventlet')import eventleteventlet.monkey_patch()