Je travaille sur une nouvelle plate-forme de développement utilisant nginx/gunicorn et Flask pour mon application.
En ce qui concerne les opérations, tout fonctionne bien - le problème que je rencontre concerne le débogage de la couche Flask. Quand il y a une erreur dans mon code, je reçois simplement une erreur 500 directement renvoyée au navigateur et rien ne s'affiche sur la console ou dans mes journaux.
J'ai essayé de nombreuses configurations/options différentes .. Je suppose que je dois manquer quelque chose d'évident.
Mon gunicorn.conf:
import os
bind = '127.0.0.1:8002'
workers = 3
backlog = 2048
worker_class = "sync"
debug = True
proc_name = 'gunicorn.proc'
pidfile = '/tmp/gunicorn.pid'
logfile = '/var/log/gunicorn/debug.log'
loglevel = 'debug'
Un exemple de code Flask qui borks- testserver.py:
from flask import Flask
from flask import render_template_string
from werkzeug.contrib.fixers import ProxyFix
app = Flask(__name__)
@app.route('/')
def index():
n = 1/0
return "DIV/0 worked!"
Et enfin, la commande pour exécuter l'application du flacon dans gunicorn:
gunicorn -c gunicorn.conf.py testserver:app
Merci à vous tous
La configuration Flask est entièrement séparée de celle de gunicorn. Après la documentation de Flask sur les fichiers de configuration , une bonne solution serait de changer mon source en ceci:
app = Flask(__name__)
app.config.from_pyfile('config.py')
Et dans config.py:
DEBUG = True
La solution d'acception ne fonctionne pas pour moi.
Gunicorn est un environnement de pré-forking et apparemment le débogueur Flask ne fonctionne pas dans un environnement de forking .
Attention
Même si le débogueur interactif ne fonctionne pas dans forking environnements (ce qui rend presque impossible à utiliser sur serveurs de production) [...]
Même si vous définissez app.debug = True
, vous n'obtiendrez toujours qu'une page vide contenant le message Erreur interne du serveur si vous exécutez avec gunicorn testserver:app
. Le mieux que vous puissiez faire avec gunicorn est de l'exécuter avec gunicorn --debug testserver:app
. Cela vous donne la trace en plus du message Erreur interne du serveur. Cependant, il s’agit simplement de la même trace de texte que celle que vous voyez dans le terminal et non du débogueur Flask.
L'ajout de la section if __...
au testserver.py et l'exécution de python testserver.py
pour démarrer le serveur en développement procurent le débogueur Flask. En d'autres termes, n'utilisez pas gunicorn en développement si vous voulez le débogueur Flask.
app = Flask(__name__)
app.config['DEBUG'] = True
if __== '__main__':
app.run()
Personnellement, j'aime toujours utiliser foreman start
, au lieu de python testserver.py
puisque il configure toutes les variables env pour moi . Pour que cela fonctionne:
Procfile
web: bin/web
bin/web
, le fichier est relatif à la racine du projet#!/bin/sh
if [ "$FLASK_ENV" == "development" ]; then
python app.py
else
gunicorn app:app -w 3
fi
.env
relatif à la racine du projet avec le contenu suivant (docs here )FLASK_ENV=development
DEBUG=True
De plus, n'oubliez pas de changer la ligne app.config['DEBUG']...
dans testserver.py
pour quelque chose qui n'exécutera pas Flask en mode débogage en production.
app.config['DEBUG'] = os.environ.get('DEBUG', False)
Pour les utilisateurs Heroku , il existe une solution plus simple que de créer un script bin/web comme suggéré par Nick.
Au lieu de foreman start
, utilisez simplement foreman run python app.py
si vous souhaitez déboguer votre application en développement.
Essayez de définir le drapeau de débogage sur la commande d'exécution comme si
gunicorn -c gunicorn.conf.py --debug testserver:app
et conservez le DEBUG = True
dans votre application Flask. Il doit y avoir une raison pour laquelle votre option de débogage n'est pas appliquée à partir du fichier de configuration, mais pour le moment, la note ci-dessus devrait vous aider.
J'ai eu un problème similaire lors de l'exécution de flacon sous gunicorn je ne voyais pas stacktraces dans le navigateur (je devais consulter les journaux à chaque fois). La définition de DEBUG, FLASK_DEBUG ou de tout autre élément mentionné sur cette page ne fonctionnait pas. Finalement j'ai fait ça:
app = Flask(__name__)
app.config.from_object(settings_map[environment])
if environment == 'development':
from werkzeug.debug import DebuggedApplication
app_runtime = DebuggedApplication(app, evalex=False)
else:
app_runtime = app
Remarque: evalex est désactivé car le débogage interactif ne fonctionne pas avec le forking (gunicorn).