Как использовать Flask- Script и Gunicorn
Я работаю над флеш-приложением, используя Flask, встроенную в dev-сервер. Я запускаю его с помощью Flask- Script. Я хочу переключиться на использование Gunicorn в качестве веб-сервера. Для этого мне нужно написать какой-то код интеграции между Flask- Script и Gunicorn? Или Flask- Script не подходит для запуска приложения с помощью Gunicorn?
Спасибо заранее!
Опоры @sean-lynch. Следующее работает, проверенный код основан на его ответе.
Изменения, которые я сделал, были:
-
Параметры, которые не распознаются Gunicorn, удаляются из sys.argv
в remove_non_gunicorn_command_line_args()
, прежде чем пытаться запустить сервер. В противном случае Gunicorn выдает сообщение об ошибке: error: unrecognized arguments: --port 5010
. Я удаляю -p
, потому что, несмотря на то, что это не вызывает ошибки, это происходит только потому, что Gunicorn считает свою короткую форму своей опцией pidfile
, которая явно не является тем, что предполагалось.
-
Подпись GunicornServer.handle() изменена для соответствия методу, который он переопределяет, то есть Command.handle()
-
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())
Ответы
Ответ 1
Как сказал Дайват, вы можете просто использовать приложение Flask прямо с Gunicorn.
Если вы все еще хотите использовать Flask- Script, вам нужно создать пользовательский Command
. У меня нет опыта с Gunicorn, но я нашел аналогичное решение для Flask-Actions и поместил его в Flask- Script, хотя следует предупредить, он не проверен.
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()
Затем вы можете зарегистрировать его для замены Flask локального сервера разработки в python manage.py runserver
manager.add_command("runserver", GunicornServer())
или зарегистрируйтесь как новая команда, например python manage.py gunicorn
manager.add_command("gunicorn", GunicornServer())
Изменить июнь 2016. С помощью последней версии Flask- Script измените метод handle
на __call__
. старая фляжка script vs новая фляжка script
Ответ 2
Я написал лучшую версию GunicornServer на основе Sean Lynch's, теперь команда принимает все аргументы о стрельбе
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())
Ответ 3
Основываясь на ответе Шона, я также написал более предпочтительную для меня версию.
@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()
вы можете запустить пулемет, используя команду вроде этого python manager.py gunicorn
Ответ 4
Флажок действительно имеет документы для запуска Gunicorn здесь.
Вы должны помнить, что Gunicorn - сервер WSGI с некоторыми тонкостями.
Ответ 5
Далее я расскажу об ответе @NinjaDQ. Если вы хотите использовать атрибут app_uri
для определения, например, файла конфигурации приложения флагов и аргументов командной строки в одно и то же время, вам нужно использовать WSGIApplication
. Проблема в том, что это приложение overrides
аргументы командной строки, поэтому необходимо игнорировать 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()
Ответ 6
Основываясь на менганском ответе, получите все аргументы из конфигурации приложения.
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()