web-dev-qa-db-fra.com

Comment puis-je ajouter un fil de fond à la fiole?

Je suis en train d'écrire un petit serveur de jeu pour essayer le flacon. Le jeu expose une API via REST aux utilisateurs. Il est facile pour les utilisateurs d’exécuter des actions et d’interroger des données, mais j’aimerais desservir le "monde du jeu" en dehors de la boucle app.run () pour mettre à jour les entités de jeu, etc. Étant donné que Flask est implémenté de manière aussi propre, j'aimerais pour voir s'il existe un moyen Flask de le faire.

65
Marinus

Vos threads supplémentaires doivent être lancés à partir de la même application appelée par le serveur WSGI.

L'exemple ci-dessous crée un thread en arrière-plan qui s'exécute toutes les 5 secondes et manipule des structures de données également disponibles pour les fonctions routées Flask.

import threading
import atexit
from flask import Flask

POOL_TIME = 5 #Seconds

# variables that are accessible from anywhere
commonDataStruct = {}
# lock to control access to variable
dataLock = threading.Lock()
# thread handler
yourThread = threading.Thread()

def create_app():
    app = Flask(__name__)

    def interrupt():
        global yourThread
        yourThread.cancel()

    def doStuff():
        global commonDataStruct
        global yourThread
        with dataLock:
        # Do your stuff with commonDataStruct Here

        # Set the next thread to happen
        yourThread = threading.Timer(POOL_TIME, doStuff, ())
        yourThread.start()   

    def doStuffStart():
        # Do initialisation stuff here
        global yourThread
        # Create your thread
        yourThread = threading.Timer(POOL_TIME, doStuff, ())
        yourThread.start()

    # Initiate
    doStuffStart()
    # When you kill Flask (SIGTERM), clear the trigger for the next thread
    atexit.register(interrupt)
    return app

app = create_app()          

Appelez-le de Gunicorn avec quelque chose comme ça:

gunicorn -b 0.0.0.0:5000 --log-config log.conf --pid=app.pid myfile:app
64
caio

En plus d'utiliser des threads purs ou la file d'attente de céleri (notez que flask-celery n'est plus nécessaire), vous pouvez également consulter flask-apscheduler:

https://github.com/viniciuschiele/flask-apscheduler

Un exemple simple copié de https://github.com/viniciuschiele/flask-apscheduler/blob/master/examples/jobs.py :

from flask import Flask
from flask_apscheduler import APScheduler


class Config(object):
    JOBS = [
        {
            'id': 'job1',
            'func': 'jobs:job1',
            'args': (1, 2),
            'trigger': 'interval',
            'seconds': 10
        }
    ]

    SCHEDULER_API_ENABLED = True


def job1(a, b):
    print(str(a) + ' ' + str(b))

if __== '__main__':
    app = Flask(__name__)
    app.config.from_object(Config())

    scheduler = APScheduler()
    # it is also possible to enable the API directly
    # scheduler.api_enabled = True
    scheduler.init_app(app)
    scheduler.start()

    app.run()
3
Andreas Bergström

On dirait qu'il existe une manière astucieuse de le faire , mais je ne pense pas que cela soit techniquement pris en charge.

J'ai aussi trouvé cette réponse , qui parle d'utiliser le céleri-flacon pour cela.

3
girasquid

Vous pouvez jeter un oeil à RQ .

Consultez également le formidable tutoriel de Miguel Greenberg sur les tâches en arrière-plan utilisant RQ et Flask.

0
Levon