RuntimeError:在请求上下文之外工作

时间:2014-12-01 00:42:46

标签: python websocket flask flask-socketio

我正在尝试创建一个' keepalive' websocket线程一旦有人连接到页面但每10秒钟向浏览器发送一次发出但是收到错误并且不确定如何绕过它。知道如何使这项工作。一旦“断开连接”,我将如何杀死这个帖子?发送了吗?

谢谢!

@socketio.on('connect', namespace='/endpoint')
def test_connect():
    emit('my response', {'data': '<br>Client thinks i\'m connected'})

    def background_thread():
        """Example of how to send server generated events to clients."""
        count = 0
        while True:
            time.sleep(10)
            count += 1
            emit('my response', {'data': 'websocket is keeping alive'}, namespace='/endpoint')

    global thread
    if thread is None:
        thread = Thread(target=background_thread)
        thread.start()

1 个答案:

答案 0 :(得分:8)

您编写后台线程的方式要求它知道客户端是谁,因为您要向其发送直接消息。因此,后台线程需要访问请求上下文。在Flask中,您可以使用copy_current_request_context装饰器在线程中安装当前请求上下文的副本:

@copy_current_request_context
def background_thread():
    """Example of how to send server generated events to clients."""
    count = 0
    while True:
        time.sleep(10)
        count += 1
        emit('my response', {'data': 'websocket is keeping alive'}, namespace='/endpoint')

几个笔记:

  • 当您发送回客户端时,没有必要设置命名空间,默认情况下,emit调用将位于客户端使用的相同命名空间上。在请求上下文之外广播或发送消息时,需要指定命名空间。
  • 请记住,您的设计需要为每个连接的客户端提供单独的线程。拥有一个向所有客户端广播的后台线程会更有效。有关示例,请参阅我在Github存储库中的示例应用程序:https://github.com/miguelgrinberg/Flask-SocketIO/tree/master/example

要在客户端断开连接时停止线程,您可以使用任何多线程机制让线程知道它需要退出。例如,这可以是您在disconnect事件上设置的全局变量。一个易于实现的不太好的替代方法是等待emit在客户端离开时引发异常并使用它来退出线程。