Comment utiliser flasque-Script et Gunicorn
je travaille sur une application Flask en utilisant le serveur Flask intégré dans dev server. Je l'ai commencé en utilisant Flask-Script. Je veux passer à L'utilisation de Gunicorn comme serveur web. Pour ce faire, ai-je besoin d'écrire une sorte de code d'intégration entre Flask-Script et Gunicorn? Ou est-ce que Flask-Script n'est pas pertinent pour lancer L'application avec Gunicorn?
Merci d'avance!
accessoires à @ sean-lynch. Ce qui suit est le code de travail Testé sur la base de sa réponse. Les changements que j'ai faits étaient les suivants:
les Options qui ne sont pas reconnues par Gunicorn sont retirées de
sys.argv
remove_non_gunicorn_command_line_args()
avant d'essayer de démarrer le serveur. Sinon Gunicorn lance une erreur avec un message comme celui-ci:error: unrecognized arguments: --port 5010
. - Je supprimer-p
parce que, même si elle ne cause pas l'erreur, C'est seulement parce que Gunicorn pense que c'est la forme courte de sonpidfile
option, qui n'est évidemment pas ce qu'on veut.GunicornServer.handle() signature modifiée pour correspond à la méthode qu'il supplante, C'est-à-dire la commande.la poignée()
-
from flask_script import Command
from gunicorn.app.base import Application
class GunicornServer(Command):
description = 'Run the app within Gunicorn'
def __init__(self, host='127.0.0.1', port=8000, workers=6):
self.port = port
self.host = host
self.workers = workers
def get_options(self):
return (
Option('-t', '--host',
dest='host',
default=self.host),
Option('-p', '--port',
dest='port',
type=int,
default=self.port),
Option('-w', '--workers',
dest='workers',
type=int,
default=self.workers),
)
def handle(self, app, *args, **kwargs):
host = kwargs['host']
port = kwargs['port']
workers = kwargs['workers']
def remove_non_gunicorn_command_line_args():
import sys
args_to_remove = ['--port','-p']
def args_filter(name_or_value):
keep = not args_to_remove.count(name_or_value)
if keep:
previous = sys.argv[sys.argv.index(name_or_value) - 1]
keep = not args_to_remove.count(previous)
return keep
sys.argv = filter(args_filter, sys.argv)
remove_non_gunicorn_command_line_args()
from gunicorn import version_info
if version_info < (0, 9, 0):
from gunicorn.arbiter import Arbiter
from gunicorn.config import Config
arbiter = Arbiter(Config({'bind': "%s:%d" % (host, int(port)),'workers': workers}), app)
arbiter.run()
else:
class FlaskApplication(Application):
def init(self, parser, opts, args):
return {
'bind': '{0}:{1}'.format(host, port),
'workers': workers
}
def load(self):
return app
FlaskApplication().run()
manager.add_command('gunicorn', GunicornServer())
6 réponses
comme Dhaivat l'a dit, Vous pouvez utiliser votre flasque directement avec Gunicorn.
si vous voulez toujours utiliser Flask-Script, vous devrez créer un custom Command
. Je n'ai pas d'expérience avec Gunicorn, mais j'ai trouvé un similaire solution pour Flacon-Actions et porté à en Flacon de Script, mais attention, c'est non testé.
from flask_script import Command, Option
class GunicornServer(Command):
description = 'Run the app within Gunicorn'
def __init__(self, host='127.0.0.1', port=8000, workers=4):
self.port = port
self.host = host
self.workers = workers
def get_options(self):
return (
Option('-H', '--host',
dest='host',
default=self.host),
Option('-p', '--port',
dest='port',
type=int,
default=self.port),
Option('-w', '--workers',
dest='workers',
type=int,
default=self.workers),
)
def handle(self, app, host, port, workers):
from gunicorn import version_info
if version_info < (0, 9, 0):
from gunicorn.arbiter import Arbiter
from gunicorn.config import Config
arbiter = Arbiter(Config({'bind': "%s:%d" % (host, int(port)),'workers': workers}), app)
arbiter.run()
else:
from gunicorn.app.base import Application
class FlaskApplication(Application):
def init(self, parser, opts, args):
return {
'bind': '{0}:{1}'.format(host, port),
'workers': workers
}
def load(self):
return app
FlaskApplication().run()
vous pouvez alors soit l'enregistrer pour remplacer le flacon serveur de développement localpython manage.py runserver
manager.add_command("runserver", GunicornServer())
ou vous inscrire comme une nouvelle commande telle que python manage.py gunicorn
manager.add_command("gunicorn", GunicornServer())
Édition Juin 2016: avec la dernière version de Flask-Script, changez la méthode handle
__call__
. vieux flacon de script et nouveau flacon-script
j'ai écrit une meilleure version de GunicornServer basé sur Sean Lynch, la commande accepte maintenant tous les arguments de gunicorn
from yourapp import app
from flask.ext.script import Manager, Command, Option
class GunicornServer(Command):
"""Run the app within Gunicorn"""
def get_options(self):
from gunicorn.config import make_settings
settings = make_settings()
options = (
Option(*klass.cli, action=klass.action)
for setting, klass in settings.iteritems() if klass.cli
)
return options
def run(self, *args, **kwargs):
from gunicorn.app.wsgiapp import WSGIApplication
app = WSGIApplication()
app.app_uri = 'manage:app'
return app.run()
manager = Manager(app)
manager.add_command("gunicorn", GunicornServer())
basé sur la réponse du Sean, j'ai aussi écrit une version plus préférée à moi.
@manager.option('-h', '--host', dest='host', default='127.0.0.1')
@manager.option('-p', '--port', dest='port', type=int, default=6969)
@manager.option('-w', '--workers', dest='workers', type=int, default=3)
def gunicorn(host, port, workers):
"""Start the Server with Gunicorn"""
from gunicorn.app.base import Application
class FlaskApplication(Application):
def init(self, parser, opts, args):
return {
'bind': '{0}:{1}'.format(host, port),
'workers': workers
}
def load(self):
return app
application = FlaskApplication()
return application.run()
vous pouvez exécuter le gunicorn en utilisant la commande suivantepython manager.py gunicorn
Flask a en fait docs pour exécuter Gunicorn ici.
vous devez vous rappeler que Gunicorn est un serveur WSGI avec quelques subtilités.
j'expliquerai plus en détail la réponse de @NinjaDQ. Si vous souhaitez utiliser app_uri
attribut pour définir par exemple le fichier de configuration de l'application flask et les arguments personnalisés en ligne de commande en même temps, vous devez utiliser WSGIApplication
. Le problème est que cette application overrides
les arguments de la ligne de commande il est donc nécessaire d'ignorer le sys.argv
.
from gunicorn.app.base import Application
class FlaskApplication(Application):
def init(self, parser, opts, args):
return {
"bind": "{0}:{1}".format(host, port),
"workers": 4
}
def chdir(self):
# chdir to the configured path before loading,
# default is the current dir
os.chdir(self.cfg.chdir)
# add the path to sys.path
sys.path.insert(0, self.cfg.chdir)
def load_wsgiapp(self):
self.chdir()
# load the app
return util.import_app(self.app_uri)
def load(self):
return self.load_wsgiapp()
# Important! Do not pass any cmd line arguments to gunicorn
sys.argv = sys.argv[:2]
wsgi_app = FlaskApplication()
wsgi_app.app_uri = "manage:create_app('{0}')".format(config_file)
return wsgi_app.run()
basé sur la réponse de menghan, recevez tous les arguments de L'Application config.
from flask_script import Command, Option
class GunicornApp(Command):
def get_options(self):
from gunicorn.config import make_settings
settings = make_settings()
options = (
Option(*klass.cli, dest=klass.name, default=klass.default)
for setting, klass in settings.items() if klass.cli
)
return options
def __call__(self, app=None, *args, **kwargs):
from gunicorn.app.base import Application
class FlaskApplication(Application):
def init(self, parser, opts, args):
return kwargs
def load(self):
return app
FlaskApplication().run()