Python - Flask-SocketIO отправляет сообщение из потока: не всегда работает
Я нахожусь в ситуации, когда я получаю сообщение от клиента. Внутри функции, которая обрабатывает этот запрос (@ socketio.on), я хочу вызвать функцию, в которой выполняется некоторая тяжелая работа. Это не должно приводить к блокировке основного потока, и считается, что клиент будет проинформирован, как только работа будет завершена. Таким образом, я начинаю новую тему.
Теперь я сталкиваюсь с действительно странным поведением: сообщение никогда не достигает клиента. Однако код достигает той конкретной точки, куда отправляется сообщение. Еще более удивительным является тот факт, что если в потоке ничего не происходит, кроме сообщения, отправляемого клиенту, то ответ на самом деле находит свой путь к клиенту.
Подводя итог: если что-то требует значительных вычислительных ресурсов перед отправкой сообщения, оно не доставляется, в противном случае это происходит.
Как сказаноВот а такжеВототправка сообщений из потока клиентам не проблема вообще:
Во всех примерах, показанных до этого момента, сервер отвечает на событие, отправленное клиентом. Но для некоторых приложений сервер должен быть отправителем сообщения. Это может быть полезно для отправки клиентам уведомлений о событиях, которые произошли на сервере, например, в фоновом потоке.
Вот пример кода. При удалении комментирующих острых предметов (#) сообщение ('foo from thread') не находит своего пути к клиенту, в противном случае это делает.
from flask import Flask
from flask.ext.socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
from threading import Thread
import time
@socketio.on('client command')
def response(data):
thread = Thread(target = testThreadFunction)
thread.daemon = True
thread.start()
emit('client response', ['foo'])
def testThreadFunction():
# time.sleep(1)
socketio.emit('client response', ['foo from thread'])
socketio.run(app)
Я использую Python 3.4.3, Flask 0.10.1, flask-socketio1.2, eventlet 0.17.4.
Этот образец может быть скопирован и вставлен в файл .py, и поведение может быть немедленно воспроизведено.
Может кто-нибудь объяснить это странное поведение?
Обновить
Кажется, это ошибка Eventlet. Если я сделаю:
socketio = SocketIO(app, async_mode='threading')
Это заставляет приложение не использовать eventlet, хотя оно установлено.
Однако для меня это неприменимое решение, так как использование 'многопоточности', поскольку async_mode отказывается принимать двоичные данные. Каждый раз, когда я отправляю некоторые двоичные данные с клиента на сервер, он говорит:
WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.
Третий вариант, использующий gevent в качестве async_mode, не работает для меня, так как gevent еще не поддерживает python 3.
Так какие-нибудь другие предложения?