Flask, Python и Socket.io: получение «RuntimeError: работа вне контекста запроса» при отключении от потока. Время - PullRequest
0 голосов
/ 26 января 2020

Я пытаюсь написать простой сервер, который отключает пользователя после минуты бездействия. Я нашел простой способ сделать это с помощью threading.Timer (перезапуск таймера каждый раз, когда происходит активность).

Я получаю RuntimeError при использовании отключения в Timer. попытался использовать app.app_context и app.test_request_context, но либо я не знаю, как и где их использовать, либо он просто не работает.

код сервера:

from flask import Flask, request
from flask_socketio import SocketIO, emit, disconnect
from threading import Timer

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
sio = SocketIO(app)
clients = {}


class Client:
    def __init__(self, user, sid, client_time):
        self.user = user
        self.sid = sid
        self.client_time = client_time
        self.activity_timer = Timer(10, self.disc_after_60)
        self.start_timer()

    def disc_after_60(self):
        disconnect(self.sid)
        del clients[self.user]

    def start_timer(self):
        if self.activity_timer.is_alive():
            self.activity_timer.cancel()
            self.activity_timer.start()
        else:
            self.activity_timer.start()


@sio.on('register')
def handle_register(client_user, client_time):
    clients[client_user] = Client(client_user, request.sid, client_time)
    emit('message', ("SERVER", f"{client_user} has joined the server!"), broadcast=True)

на стороне клиента Я просто подключаюсь с помощью регистра.

полное сообщение об ошибке:

Exception in thread Thread-8:
Traceback (most recent call last):
  File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 1254, in run
    self.function(*self.args, **self.kwargs)
  File "C:\Users\idshi\PycharmProjects\PyChat excersize\Server\fsserver.py", line 24, in disc_after_60
    disconnect(self.sid)
  File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\site-packages\flask_socketio\__init__.py", line 919, in disconnect
    socketio = flask.current_app.extensions['socketio']
  File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\site-packages\werkzeug\local.py", line 348, in __getattr__
    return getattr(self._get_current_object(), name)
  File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\site-packages\werkzeug\local.py", line 307, in _get_current_object
    return self.__local()
  File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\site-packages\flask\globals.py", line 52, in _find_app
    raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().  See the
documentation for more information.

Я был бы рад, если бы кто-то мог помочь мне с этим. Заранее спасибо.

1 Ответ

0 голосов
/ 28 января 2020

Функция disconnect() должна вызываться с установленным контекстом приложения, поскольку это единственный способ узнать, что такое экземпляр приложения.

Попробуйте это:

    def disc_after_60(self):
        with app.app_context():
            disconnect(sid=self.sid, namespace='/')
        del clients[self.user]
...