web-dev-qa-db-fra.com

Exécuter le code après le démarrage de l'application du flacon

Mon objectif est d’exécuter du code arbitraire après le démarrage de mon application Flask. Voici ce que j'ai

def run():
    from webapp import app
    app.run(debug=True, use_reloader=False)

Idéalement, je pourrais simplement faire ceci:

def run():
    from webapp import app
    app.run(debug=True, use_reloader=False)
    some_code()

Mais le code ne continue pas au-delà de app.run(), ainsi some_code () ne s'exécute jamais.

La solution sur laquelle je travaille en ce moment consiste à exécuter some_code () dans un thread distinct de app.run (), créer un avant la première requête fonction qui définit ceci: 

app.is_running = True

Ensuite, demandez à some_code () de lancer une requête de base vers une application afin que le code "avant la première requête" soit exécuté. Ceci est assez compliqué et va être difficile à documenter. Je préférerais utiliser le paramètre app.is_running qui est déjà fourni dans Flask ou utiliser un décorateur @app.after_server_start, mais à ma connaissance, aucun de ceux-ci n'existe.

Aidez-moi à améliorer ce code?


Posthume: Chaque fois que je pense à ce problème, cela me fait souhaiter qu’un décorateur @app.after_server_start existe.

27
Cyrin

Si vous devez exécuter du code après le démarrage de votre application de flacon, mais strictement avant la première requête, même si cela ne peut pas être déclenché par l'exécution de la première requête comme @ app.before_first_request, vous devez utiliser pourrait sous-classer la classe Server et écraser la méthode __ call __ au lieu d'écraser la commande runserver avec @ manager.command:

from flask import Flask
from flask_script import Manager, Server

def custom_call():
    #Your code
    pass

class CustomServer(Server):
    def __call__(self, app, *args, **kwargs):
        custom_call()
        #Hint: Here you could manipulate app
        return Server.__call__(self, app, *args, **kwargs)

app = Flask(__name__)
manager = Manager(app)

# Remeber to add the command to your Manager instance
manager.add_command('runserver', CustomServer())

if __== "__main__":
    manager.run()

De cette façon, vous ne remplacez pas les options par défaut de la commande runserver.

20
Ismael

Utilisez Flask-Script pour exécuter votre application, puis écrasez la classe/méthode runserver comme ceci.

# manage.py

from flask.ext.script import Manager

from myapp import app

manager = Manager(app)

def crazy_call():
    print("crazy_call")

@manager.command
def runserver():
    app.run()
    crazy_call()

if __== "__main__":
    manager.run()
9
CESCO

J'ai rencontré le même problème dans une de mes applications. Je voulais lancer un planificateur au démarrage de l'application, ce qui permettrait de lancer des travaux à intervalles réguliers. Depuis que je déploie mes applications dans des conteneurs Docker, j'ai fini par ajouter un point de terminaison "d'intégrité", qui ne renvoie qu'un 200, et dans mon fichier de docker, ce dernier a été configuré:

HEALTHCHECK CMD curl --fail http://localhost:8080/alive || exit 1

Le comportement par défaut consiste à exécuter cette commande toutes les 30 secondes et la première exécution lance commodément ma méthode init () . https://docs.docker.com/engine/reference/builder/#healthcheck

0
skelly