Как сделать серверную l oop бесконечной и неблокируемой одновременно без использования потоков / фоновых заданий? - PullRequest
0 голосов
/ 15 февраля 2020

Мне нужен бесконечный l oop для запуска на стороне сервера и передачи некоторой информации за одну итерацию.

Кроме того, мне нужно убедиться, что она запускается только один раз - предпочтительно при запуске сервера - и не вызвано различными пользователями, использующими приложение.

Тогда я бы хотел по возможности избежать дополнительного стека (многопоточность, фоновые задания и т. Д. c.).

Вот задача:

@app.route('/refresh_games_list_periodically')
def refresh_games_list_periodically():
    while True:
        response = {
            'games_list': games_manager.get_nonexpired_games(),
        }
        socketio.emit('games_list_refreshed', response)
        time.sleep(1)

Запускается всякий раз, когда 'index. html' отображается:

@app.route('/')
def index(): 
    return render_template('index.html')

index. html:

fetch("{{url_for('refresh_games_list_periodically') }}")

Полный код:

import time

from flask import (
    Flask, 
    render_template, 
    jsonify,
    request,
)
from flask_socketio import SocketIO, emit

from minesweeper import Game, GamesManager

games_manager = GamesManager()

app = Flask(__name__)
socketio = SocketIO(app)

@app.route('/refresh_games_list_periodically')
def refresh_games_list_periodically():
    while True:
        response = {
            'games_list': games_manager.get_nonexpired_games(),
        }
        socketio.emit('games_list_refreshed', response)
        time.sleep(1)

@app.route('/')
def index(): 
    return render_template('index.html')

Проблема в настоящее время является то, что всякий раз, когда новый пользователь вводит «index. html», запускается еще одна итерация l oop, кроме старой.

Я пытался использовать некоторые логические флаги, чтобы пометить представление как уже вызвал, но не смог сделать это правильно в контексте Flask.

Тогда я подумал, что мог бы сделать refresh_games_list_periodically нормальной функцией, а не представлением, и просто вызвать ее в моем приложении Flask перед представлениями. Но тогда while l oop будет блокироваться, и страница не будет отображаться:

import time

from flask import (
    Flask, 
    render_template, 
    jsonify,
    request,
)
from flask_socketio import SocketIO, emit

from minesweeper import Game, GamesManager

games_manager = GamesManager()

app = Flask(__name__)
socketio = SocketIO(app)

refresh_games_list_periodically()

def refresh_games_list_periodically():
    while True: # WILL BLOCK
        response = {
            'games_list': games_manager.get_nonexpired_games(),
        }
        socketio.emit('games_list_refreshed', response)
        time.sleep(1)

@app.route('/')
def index(): 
    return render_template('index.html')

Как еще я могу это сделать?

1 Ответ

0 голосов
/ 15 февраля 2020
thread = threading.Thread(target=refresh_games_list_periodically)
thread.start() 

Я думаю ... Я думаю, что это не очень хорошая идея, и вам, вероятно, лучше запустить сокет l oop в одном процессе и ваше приложение flask отдельно

...