Python-Flask-SocketIO从线程发送消息:并非始终有效 [英] Python - Flask-SocketIO send message from thread: not always working

查看:551
本文介绍了Python-Flask-SocketIO从线程发送消息:并非始终有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我处于从客户端接收消息的情况.在处理该请求的函数中(@ socketio.on),我想调用一个完成一些繁重工作的函数.这不应导致阻塞主线程,并且在工作完成后,可以认为已通知客户端.因此,我开始了一个新线程.

I am in the situation where I receive a message from the client. Within the function that handles that request (@socketio.on) I want to call a function where some heavy work is done. This should not result in blocking the main thread and the client is thought to be informed once the work is done. Thus I start a new thread.

现在,我遇到了一个非常奇怪的行为: 该消息永远不会到达客户端.但是,代码到达了发送消息的那个特定位置. 更令人惊讶的是,如果除了发送给客户端的消息之外线程中什么也没有发生,那么答案实际上就找到了发送给客户端的方式.

Now I encounter a really strange behavior: The message never reaches the client. However, the code reaches that particular spot where the message is sent. Even more surprising is the fact that if there is nothing happening in the thread except for the message being sent to the client then the answer actually finds its way to the client.

总结一下: 如果在发送消息之前发生了一些计算量大的事情,那么它就不会被传递,否则就会被传递.

To sum it up: If something computationally intensive happens before the message is sent it is not being delivered, otherwise it is.

就像说的那样这里此处,将消息从线程发送到客户端不是问题全部:

Like it is said here and here, sending messages from a thread to the clients is not a problem at all:

在所示的所有示例中,直到现在,服务器都响应客户端发送的事件.但是对于某些应用程序,服务器必须是消息的始发者.将通知发送给客户端有关起源于服务器(例如,后台线程)中的事件的通知很有用.

In all the examples shown until this point the server responds to an event sent by the client. But for some applications, the server needs to be the originator of a message. This can be useful to send notifications to clients of events that originated in the server, for example in a background thread.

这是示例代码.删除注释的尖笔符号(#)时,消息(来自线程的foo")找不到通往客户端的方式,否则会到达.

Here is a sample code. When removing the commenting sharps (#) the message ('foo from thread') does not find its way to the client, otherwise it does.

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.

I am using Python 3.4.3, Flask 0.10.1, flask-socketio1.2, eventlet 0.17.4.

可以将该示例复制并粘贴到.py文件中,并可以立即重现该行为.

This sample can be copied and pasted in a .py file and the behavior can be instantly reproduced.

有人可以解释这种奇怪的行为吗?

Can somebody explain this strange behavior?

更新

这似乎是eventlet的错误.如果我这样做:

It seems to be a bug of eventlet. If I do:

socketio = SocketIO(app, async_mode='threading')

它强制应用程序即使已安装也不要使用eventlet.

It forces the application not to use eventlet although it is installed.

但是,由于async_mode拒绝接受二进制数据,因此使用'threading'对我来说这不是适用的解决方案.每当我从客户端向服务器发送一些二进制数据时,都会说:

However, this is not an applicable solution for me as using 'threading' as async_mode refuses to accept binary data. Every time I send some binary data from the client to the server it says:

WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.

使用gevent作为async_mode的第三个选项对我不起作用,而且gevent还不支持python 3.

The third option, using gevent as the async_mode does not work for me as well as gevent does not have support for python 3 yet.

还有其他建议吗?

推荐答案

我设法通过猴子修补几个Python函数来解决此问题,这使Python使用eventlet函数代替了本机函数.这样,后台线程可以与eventlet一起正常工作.

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

这篇关于Python-Flask-SocketIO从线程发送消息:并非始终有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆