web-dev-qa-db-fra.com

Démarrer une application de flacon dans un thread séparé

Je développe actuellement une application Python sur laquelle je souhaite voir des statistiques en temps réel. Je voulais utiliser Flask afin de le rendre facile à utiliser et à comprendre.

Le problème est que mon serveur Flask doit démarrer au tout début de mon application Python et s’arrêter à la toute fin. Ça devrait ressembler à ça:

def main():
    """ My main application """
    from watcher.flask import app
    # watcher.flask define an app as in the Quickstart flask documentation.
    # See: http://flask.pocoo.org/docs/0.10/quickstart/#quickstart

    app.run() # Starting the flask application

    do_my_stuff()

    app.stop() # Undefined, for the idea 

Parce que j'ai besoin de mon contexte d'application (pour les statistiques), je ne peux pas utiliser un multiprocessing.Process. Ensuite, j'ai essayé d'utiliser un threading.Thread, mais il semblerait que Werkzeug ne l'aime pas: 

 * Running on http://0.0.0.0:10079/
Exception in thread Flask Server:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File ".../develop-eggs/watcher.flask/src/watcher/flask/__init__.py", line 14, in _run
    app.run(Host=HOSTNAME, port=PORT, debug=DEBUG)
  File ".../eggs/Flask-0.10.1-py2.7.Egg/flask/app.py", line 772, in run
    run_simple(Host, port, self, **options)
  File ".../eggs/Werkzeug-0.7-py2.7.Egg/werkzeug/serving.py", line 609, in run_simple
    run_with_reloader(inner, extra_files, reloader_interval)
  File ".../eggs/Werkzeug-0.7-py2.7.Egg/werkzeug/serving.py", line 524, in run_with_reloader
    signal.signal(signal.SIGTERM, lambda *args: sys.exit(0))
ValueError: signal only works in main thread

Comment puis-je faire cela sans exécuter Flask dans le thread principal?

31
FunkySayu

Vous exécutez Flask en mode débogage, ce qui active le rechargeur (recharge le serveur Flask lorsque votre code change). 

Flask peut très bien fonctionner dans un thread séparé, mais le rechargeur s'attend à s'exécuter dans le thread principal.


Pour résoudre votre problème, vous devez désactiver le débogage (app.debug = False) ou désactiver le rechargeur (app.use_reloader=False). 

Ceux-ci peuvent également être passés comme arguments à app.run: app.run(debug=True, use_reloader=False).

51
Thomas Orozco

si vous souhaitez accéder à un terminal ipython dans flask.__, exécutez votre application dans un thread séparé Essayez cet exemple: -

from flask import Flask                                                         
import thread
data = 'foo'
app = Flask(__name__)
@app.route("/")
def main():
    return data
def flaskThread():
    app.run()
if __== "__main__":
    thread.start_new_thread(flaskThread,())

exécuter ce fichier dans ipython

12
Rashid Mv

Réponse mise à jour pour Python 3 qui est un peu plus simple:

from flask import Flask                                                         
import threading

data = 'foo'
app = Flask(__name__)

@app.route("/")
def main():
    return data

if __== "__main__":
    threading.Thread(target=app.run).start()
1
skeller88

Dans la documentation werkzeug :

Fermeture du serveur

Nouveau dans la version 0.7.

À partir de Werkzeug 0.7, le serveur de développement fournit un moyen de Arrêtez le serveur après une requête. Cela ne fonctionne actuellement qu'avec Python 2.6 et versions ultérieures ne fonctionneront qu'avec le serveur de développement . Pour lancer l'arrêt, vous devez appeler une fonction nommée 'werkzeug.server.shutdown' dans l'environnement WSGI:

def shutdown_server(environ):
    if not 'werkzeug.server.shutdown' in environ:
        raise RuntimeError('Not running the development server')
    environ['werkzeug.server.shutdown']()
0
Burhan Khalid