在使用flask-script的应用上使用gunicorn

本文介绍了如何在使用Flask-Script的Flask应用上结合gunicorn进行部署,尤其是在Heroku平台上。通过修改Flask-Script的管理命令,实现了在gunicorn生产环境中启动应用的方法。

在使用flask-script的应用上使用gunicorn

两周前,我强烈的想要学习一点新知识,像新的语言,新的框架之类的!好让我的大脑忙碌起来,寻找了一些日子后,我决定学习现在越来越流行的云应用平台(Paas).因为我认为实战比看教程和阅读文档更有效,我决定写一个flask web程序并在Heroku上部署,经过一段时间的学习与编程后,我想要在Gunicorn生产环境中运行它.

那么,怎么让WSGI应用与gunicorn一起运行呢?在一般的情况下是很简单的,只需要运行

gunicorn appmodule:app

这样就ok了,然而我开发时使用了像如下这样的工厂模式:(一个返回Flask程序实例的函数,Flask-Manager就使用了这个模式)

def create_app(environment='development'):
app = Flask(__name__)
...
return app

flask-script提供了一个可以轻松管理你工作环境的方法,例如你可以轻松的通过下面代码运行服务

python manage.py runserver --environment development

你可以通过参数方便的配置程序,就像Heroku通过修改Procfile文件来配置环境一样

web: python manage.py runserver --environment development

这是非常好的解决方案,不幸的是它并没有向flask开发服务的外部提供任何东西,因此我使用gunicorn时不能像下面这样配置代码

python manage.py rungunicorn --environment production --gunicorn-config gunicorn.ini

我唯一能做的是:

gunicorn mymodule:create_app\(environment=\"production\"\)

这太丑了,并切根本没有用到manage.py,完全不能忍,这就是我决定折腾flask-script和gunicorn的原因,在Flask-Action的基础上改写,可以解决我的问题:

class Gunicorn(Command):
    description = 'Runs production server with gunicorn'

    def __init__(self, host='127.0.0.1', port=5000, **options):
        self.port = port
        self.host = host
        self.server_options = options

    def get_options(self):
        options = (
            Option('--gunicorn-host',
                   dest='host',
                   default=self.host),

            Option('--gunicorn-port',
                   dest='port',
                   type=int,
                   default=self.port),

            Option('--gunicorn-config',
                   dest='config',
                   type=str,
                   required=True))

        return options

    def handle(self, app, host, port, config, **kwargs):
        from ConfigParser import ConfigParser
        gc = ConfigParser()
        gc.read(config)
        section = 'default'

        bind = "%s:%s" % (host, str(port))
        workers = gc.get(section, 'workers')
        pidfile = gc.get(section, 'pidfile')
        loglevel = gc.get(section, 'loglevel')

        # Suppress argparse warnings caused by running gunicorn's argparser
        # "inside" Flask-Script which imports it too...
        warnings.filterwarnings("ignore", "^.*argparse.*$")

        from gunicorn import version_info
        if version_info >= (0, 9, 0):
            from gunicorn.app.base import Application

            class FlaskApplication(Application):
                def init(self, parser, opts, args):
                    return {
                        'bind': bind,
                        'workers': workers,
                        'pidfile': pidfile,
                        'loglevel': loglevel
                    }

                def load(self):
                    return app

            # Hacky! Do not pass any cmdline options to gunicorn!
            sys.argv = sys.argv[:2]

            print "Logging to stderr with loglevel '%s'" % loglevel
            print "Starting gunicorn..."
            FlaskApplication().run()
        else:
            raise RuntimeError("Unsupported gunicorn version! Required > 0.9.0")

而gunicorn.ini是这样的:

[default]
workers = 1
pidfile = tmp/districtrank.pid
loglevel = debug

tips

  1. 因为gunicornn也使用了argparse,所以如果我移除了Manager的sys.argv参数 gunicorn就会崩溃.也许还有更好的解决方案,但对我的需求来说已经完全足够了.
  2. 因为一些关于import的原因,需要清空输出,所以我禁止了argparse的警告,禁止警告虽然不好,但是我认为在这种情况下是可以理解的

    manager.add_command(“rungunicorn”, Gunicorn(host=host,port=port))

现在你可以使用新创建的指令来配置了

这肯定不是一段可以合并到Flask-Script的代码(迎合了我的需求,但是不是太通用,而且使用了丑陋的sys.argv并且禁止了argparse的导入警告),但是它也能正确的运行,所以我在guniorn中使用了

python manage.py rungunicorn --environment production --gunicorn-config gunicorn.ini

Works for me! ;-)

翻译原文:Running Flask app with gunicorn using a Flask-Script command (on Heroku)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值