Comment exécuter une application Flask

March 25, 2020
Rédigé par

Comment exécuter une application Flask

Pendant de nombreuses années, la célèbre application Flask « Hello, World ! » faisait 7 lignes de long. Voyez ci-dessous une capture d'écran de ce à quoi ressemblait le site Internet de Flask le 12 juin 2017 :

ancien site web de Flask

Puis cette application de démonstration a été raccourcie à seulement 5 lignes. Voici la même page, consultée le 17 juin 2017 :

nouveau site web de Flask

Comme vous pouvez le constater, le cœur de l'application n'a pas changé, mais la méthode de démarrage du serveur d'applications, oui – et de manière considérable. Alors qu'on utilisait auparavant un simple appel à la fonction app.run() dans le script d'application, il existe désormais une commande flask run, ainsi qu'une variable d'environnement FLASK_APP.

Bien que la conception du site Internet de Flask ait considérablement changé au cours des années qui ont suivi, au moment où j'écris cet article en 2020, la méthode flask run continue d'être la plus visible dans la documentation officielle du framework.

On trouve encore aujourd'hui un grand nombre d'applications et de tutoriels qui s'appuient sur la méthode app.run(). Cela s'explique notamment par le fait qu'il existe beaucoup de contenus certes plus anciens, mais qui restent pertinents pour Flask, mais également par le fait que beaucoup de gens continuent de voir la méthode app.run() comme plus pratique et plus facile à utiliser.

Nous explorerons dans cet article les avantages et les inconvénients de chacune de ces méthodes. Prêts ? Allons-y !

app.run() ou flask run, lequel utiliser ?

Commençons par la question à un million de dollars. Si vous deviez lancer une nouvelle application Flask aujourd'hui, devriez-vous utiliser app.run() ou flask run ?

Malheureusement, il n'existe pas de réponse simple à cette question.

La chose la plus importante à savoir, c'est que ces deux méthodes lancent un serveur web de développement, qui est un serveur que vous utiliserez localement sur votre propre système pendant que vous développerez votre application. Si vous essayez de comprendre comment lancer votre application sur un serveur de production, la réponse est alors simple, en effet : n'utilisez aucune des deux. Pour un déploiement en production, utilisez un serveur Web prêt pour la production tel que gunicorn ou uWSGI.

Dans un environnement de développement, les deux méthodes sont entièrement prises en charge, ce qui vous permet d'utiliser celle que vous préférez. Mais bien sûr, comme vous avez sans doute besoin d'aide pour décider, examinons-les en détail.

Utiliser flask run

La méthode flask run est la solution la plus récente, et celle qui est recommandée par le projet Flask.

La commande flask est ajoutée à votre environnement virtuel lorsque vous installez le package Flask. Elle est fournie avec trois commandes :

(venv) $ flask --help
Usage: flask [OPTIONS] COMMAND [ARGS]...

  A general utility script for Flask applications.

  Provides commands from Flask, extensions, and the application. Loads the
  application defined in the FLASK_APP environment variable, or from a
  wsgi.py file. Setting the FLASK_ENV environment variable to 'development'
  will enable debug mode.

    $ export FLASK_APP=hello.py
    $ export FLASK_ENV=development
    $ flask run

Options:
  --version  Show the flask version
  --help     Show this message and exit.

Commands:
  routes  Show the routes for the app.
  run     Run a development server.
  shell   Run a shell in the app context.

Le framework Flask inclut un module d'interface de ligne de commande qui permet aux extensions Flask tierces, voire à votre propre application, d'installer des commandes personnalisées en complément des trois commandes de base, ce qui en fait un système très puissant et extensible permettant de gérer tous les aspects de votre application Flask.

La difficulté de faire fonctionner la commande flask run, c'est qu'elle doit d'une manière ou d'une autre déterminer où se trouve votre instance d'application Flask afin de pouvoir l'importer et l'utiliser.

Comment flask run trouve votre instance d'application

Pour permettre à la commande flask run de déterminer où se trouve votre application, il faut paramétrer la variable d'environnement FLASK_APP de sorte qu'elle en indique l'emplacement. Il existe en fait cinq façons différentes de définir cette variable :

  • FLASK_APP="module:name" : il s'agit d'une nomenclature relativement standard pour les applications WSGI. Si votre instance d'application est appelée app et est définie dans un module hello.py, vous devrez définir votre variable comme FLASK_APP="hello:app". Au lieu d'un simple module, vous pouvez spécifier un chemin d'importation plus complexe en notation pointée standard, tel que FLASK_APP="server.core:app".
  • FLASK_APP="module:function()" : si vous utilisez dans votre application le modèle d'usine d'application, vous pouvez spécifier le nom de votre fonction d'usine au lieu d'un nom d'application. Flask importera la fonction et l'appellera pour créer l'application. Cette forme prend également en charge le passage d'arguments dans la fonction d'usine, par exemple FLASK_APP="hello:create_app('dev')".
  • FLASK_APP=module : si vous spécifiez uniquement un chemin d'importation sans nom d'application ou fonction d'usine, Flask importera votre module ou package et tentera de localiser l'application par lui-même. Il recherchera d'abord une variable globale app ou application, et s'il n'en trouve aucune, il inspectera toutes les variables globales du module à la recherche d'une variable définie sur une instance de classe Flask. Si aucune de ces tentatives ne produit une application, Flask recherchera enfin une fonction d'usine d'application dans votre module, laquelle pourra s'appeler create_app() ou make_app(). Si Flask ne parvient toujours pas à trouver votre application, la commande flask run se fermera en affichant un message d'erreur.
  • FLASK_APP=file.py : si votre application se trouve dans un fichier Python, vous pouvez simplement définir le nom du fichier, et Flask l'importera et trouvera l'application selon les mêmes règles que dans l'option précédente.
  • Si FLASK_APP n'est pas définie, Flask tentera d'exécuter import app et import wsgi. Si l'une de ces options réussit, il tentera ensuite de trouver l'application dans le module importé selon les mêmes règles que dans les deux options précédentes.

Si vous écrivez une courte application Flask pour un test rapide, il suffit d'appeler votre instance d'application app et de la placer dans un fichier app.py pour que flask run fonctionne sans que vous n'ayez à vous soucier des variables d'environnement.

Spécifier les options de serveur

La commande flask run` offre des options pour définir l'adresse IP et le port d'écoute du serveur, les certificats SSL, etc. :

(venv) $ flask run --help
Usage: flask run [OPTIONS]

  Run a local development server.

  This server is for development purposes only. It does not provide the
  stability, security, or performance of production WSGI servers.

  The reloader and debugger are enabled by default if FLASK_ENV=development
  or FLASK_DEBUG=1.

Options:
  -h, --host TEXT                 The interface to bind to.
  -p, --port INTEGER              The port to bind to.
  --cert PATH                     Specify a certificate file to use HTTPS.
  --key FILE                      The key file to use when specifying a
                                  certificate.
  --reload / --no-reload          Enable or disable the reloader. By default
                                  the reloader is active if debug is enabled.
  --debugger / --no-debugger      Enable or disable the debugger. By default
                                  the debugger is active if debug is enabled.
  --eager-loading / --lazy-loader
                                  Enable or disable eager loading. By default
                                  eager loading is enabled if the reloader is
                                  disabled.
  --with-threads / --without-threads
                                  Enable or disable multithreading.
  --extra-files PATH              Extra files that trigger a reload on change.
                                  Multiple paths are separated by ':'.
  --help                          Show this message and exit.

Il est important de noter que le mode débogage de Flask ne peut être spécifié via une option, et qu'il est plutôt défini via FLASK_ENV=development dans l'environnement.

Utiliser app.run()

Maintenant que nous avons passé en revue les nombreuses complexités de la commande flask run, vous devinez sans doute pourquoi app.run() est encore là.

Avec cette méthode, la question de faire en sorte que Flask sache où se trouve votre instance d'application ne se pose pas, car vous invoquez directement la méthode run() sur cet objet. C'est la raison qui fait qu'aucune variable d'environnement n'est nécessaire.

Spécifier les options de serveur

La méthode app.run() prend en charge plusieurs options, y compris toutes celles que vous pouvez fournir à la commande flask run, ainsi que quelques autres :

  • host : le nom d'hôte sur lequel on écoute.
  • port : le port du serveur web.
  • debug : si indiqué, activez ou désactivez le mode débogage.
  • load_dotenv : chargez les fichiers .env et .flaskenv les plus proches pour définir les variables d'environnement.
  • use_reloader : le serveur devrait-il relancer automatiquement le processus Python si des modules ont été modifiés ?
  • use_debugger : le système de débogage werkzeug devrait-il être utilisé ?
  • use_evalex : la fonction d'évaluation des exceptions devrait-elle être activée ?
  • extra_files : une liste des fichiers que le reloader devrait surveiller en plus des modules.
  • reloader_interval : l'intervalle du reloader en secondes.
  • reloader_type : le type de reloader à utiliser.
  • thread : le processus devrait-il traiter chaque requête dans un thread distinct ?
  • processes : si supérieur à 1, traitez chaque requête dans un nouveau processus jusqu'à ce nombre maximum de processus simultanés.
  • passthrough_errors : définissez cette option sur True pour désactiver la détection des erreurs.
  • ssl_context : un contexte SSL pour la connexion.

Inconvénients de app.run()

Si app.run() vous semble être une façon plus pratique de lancer votre application Flask, considérez les deux principaux inconvénients de cette méthode par rapport à flask run :

  • Le reloader est moins robuste. Comme l'application doit être importée avant de pouvoir invoquer la méthode run(), toute erreur qui se produit lors de l'importation de l'application entraîne l'interruption et la fermeture du reloader. Avec flask run, si l'importation de l'application échoue du fait d'une erreur, le reloader continue de surveiller les fichiers source et tente de l'importer à nouveau une fois que vous avez corrigé l'erreur.
  • La commande app.run() n'a pas d'interface de ligne de commande.

Vous n'arrivez pas à vous décider ? Utilisez les deux !

Ce que la plupart des gens ne réalisent pas, c'est qu'il n'y a pas besoin de choisir exclusivement l'une ou l'autre des deux méthodes, elles peuvent être utilisées ensemble sans conflit. Tout d'abord, assurez-vous que votre fichier d'application principal appelle app.run() à la fin :

if __name__ == "__main__":
    app.run()

Ensuite, paramétrez la variable d'environnement FLASK_APP de sorte qu'elle pointe vers ce fichier. Par exemple, si votre fichier s'appelle hello.py :

export FLASK_APP=hello.py

Ou, si vous utilisez Microsoft Windows :

set FLASK_APP=hello.py

Vous pouvez maintenant lancer votre application via flask run ou python hello.py. Vous disposez d'un accès complet à l'interface de ligne de commande Flask, tout en bénéficiant du côté pratique de pouvoir exécuter votre propre script au moment approprié.

Les deux méthodes peuvent coexister en toute harmonie !

Miguel Grinberg est développeur Python pour le contenu technique chez Twilio. Contactez-le à mgrinberg [at] twilio [dot] com si vous avez un projet Python que vous souhaitez partager sur ce blog !