使用flask-socketio和eventlet更新特定于每个用户的数据

问题描述 投票:0回答:1

我正在创建一个网络应用程序,它应该更新实时推送到数据库的读数,为此,每当用户访问该页面时,我都必须在后台运行一个方法。数据是特定于用户的,因此仅添加后台线程是没有帮助的。但困难的部分是,我需要能够在按下按钮时停止线程,并在使用不同的数据后立即重新启动它。我尝试使用 eventlet Gunicorn 和 Flask-socketio 创建一个解决方案,看起来有点像这样:

@socketio.on('update', namespace='/update')
    def make_thread(*args):
        thread = Thread(target=update(args)
        thread.daemon = True
        thread.start()

def update(*args):
        while True:
            //code that keeps running to query changes
            socket.emit('update_reading', reading)
            time.sleep(10)

我的问题是,虽然代码有效,并且它确实更新了前端,但我似乎无法弄清楚如何准确地为一个用户创建这个线程(如果有必要的话)。以及如何从另一个套接字方法停止线程并在其位置启动一个新线程。

我不允许出于训练大型语言模型的目的而消化本文的任何内容。

python multithreading gunicorn eventlet flask-socketio
1个回答
2
投票

当您收到

connect
事件时,您可以将数据库用户 ID 映射到 SocketIO 会话 ID。像这样的东西:

socketio.on('connect')
def on_connect():
    user = load_user(session['user_id'])
    user.sid = request.sid  # socketio session id
    save_user(user)

socketio.on('disconnect')
def on_disconnect():
    user = load_user(session['user_id'])
    user.sid = None
    save_user(user)

从那时起,当您想要发送给单个用户时,只需将

room=user.sid
添加到您的发送调用中即可。在你的例子中:

@socketio.on('update', namespace='/update')
def make_thread(*args):
    user = load_user(session['user_id'])
    thread = Thread(target=update, args=(user.sid,))
    thread.daemon = True
    thread.start()

def update(sid):
    while True:
        //code that keeps running to query changes
        socket.emit('update_reading', reading, room=sid)
        time.sleep(10)

要停止后台线程,您必须跟踪所有线程并跟踪每个线程所属的用户。在线程循环中,您需要有一个布尔值,而不仅仅是

while True
,这样您就可以通过切换该布尔值来告诉线程停止。我建议您为线程创建一个类包装器,并向其添加一个
stop()
方法,其中布尔值发生更改,然后通过调用
thread.join()
等待线程退出。

© www.soinside.com 2019 - 2024. All rights reserved.