【问题标题】:flask and flask-socketio flush all emit eventsflask 和 flask-socketio flush 都会发出事件
【发布时间】:2015-12-19 15:43:35
【问题描述】:

您如何刷新 flask-socketio 发出事件,以便多行流向客户端,而不是同时通过多行?

我正在与 Flask 和 flask-socketIO 合作制作一个网络应用程序,让用户可以与开源国际象棋 AI 下棋,例如 gnuchess 和 Crafty。国际象棋 AI 将他们的“想法”作为标准输出打印到服务器终端,但我正在使用 flask-socketIO 将这种想法发送给用户。

这一切都设置好了,可以工作了,但我遇到的问题是,每一行的思考都是一大块,而不是在 AI 打印时输出每一行。

例如,在对抗 gnuchess 时,服务器会打印出这样的想法:

AI thinking: Thinking...
AI thinking: 1 +4 0 2 a5
AI thinking: 1 +9 0 4 b5
AI thinking: 1 +51 0 8 d5
AI thinking: 1 +53 0 21 Nc6
AI thinking: 2 -1 0 47 Nc6 Nc3
AI thinking: 3 +53 0 155 Nc6 Nc3 Nf6
AI thinking: 4 -1 0 613 Nc6 Nf3 Nf6 Nc3

这些行会流式传输到我的服务器。在客户端,我发出 AI 行,它以 ul 的形式(现在)显示给客户端,如下所示:

4 -1 0 613 Nc6 Nf3 Nf6 Nc3
3 +53 0 155 Nc6 Nc3 Nf6
2 -1 0 47 Nc6 Nc3
1 +53 0 21 Nc6
1 +51 0 8 d5
1 +9 0 4 b5
1 +4 0 2 a5
Thinking...

以下是相关代码:

@main.route('/getpythondata')
def get_python_data():

    # gets current proc by finding user's most recent game...
    current_game = get_current_game(current_user)
    current_proc = get_current_proc(current_game)
    line = current_proc.stdout.readline().rstrip()
    socketio.emit(
            'echo',
            {'echo': line})
    # for gnu chess
    if current_game.ai == "GNU chess":
        while ("My move is" not in line):
            socketio.emit(
                'echo',
                {'echo': line})
            print "AI thinking: " + line
            line = current_proc.stdout.readline().rstrip()

        colon_index = line.index(":")
        line_length = len(line)
        pythondata = line[(colon_index + 2):(line_length)]
        current_game.cpu_moves.append(pythondata)
        return json.dumps(pythondata)

这里的问题是所有 socketio.emit 事件在烧瓶路由返回后作为一大块文本出现。也许他们被困在缓冲区中?有没有办法把它们冲洗掉?

"print "AI thinking:" + line 代码将多行文本流向服务器,一次一行,就在 AI 输出它们时。但是,socketio.emit 代码全部通过一次到服务器客户端,而不是逐行流式传输。

有什么想法吗?

【问题讨论】:

    标签: python websocket socket.io flask-socketio


    【解决方案1】:

    socketio.emit() 语句之后使用eventlet.sleep(0)

    当然你必须import eventlet

    来源:https://github.com/miguelgrinberg/Flask-SocketIO/issues/141

    【讨论】:

    • 大声感谢您的回复。你在那里的车队实际上是我和米格尔的车队。
    • 哈哈很好,我没听懂是你:p
    【解决方案2】:

    首先导入socketio对象(确保路径指向你创建它的地方)

    from .. import socketio
    

    然后使用

    socketio.sleep(0)
    

    我创建了一个函数来帮我睡觉:)

    def send_status(data):
        emit('status', data, json=True)
        socketio.sleep(0)
    

    用我想作为 JSON 发送的字符串调用它

    elehelper.send_status({'code': 201, 'message': 'Jana\'s skull stripper started!'})
    

    【讨论】: