用gunicorn部署flask报错

新手上路,请多包涵

问题描述

学习flask时候做了一个网站 用flask run可以正常运行
想用gunicorn部署一直启动不起来 而且网上大部分部署都是用flask 1.0以前的版本 相关的资料很少
想问一下 应该如何正确启动

相关代码

root@iZuf6cbarncpdr9s9j5ktcZ:/WebForTrans# export FLASK_APP=Yippee
root@iZuf6cbarncpdr9s9j5ktcZ:/WebForTrans# flask run --host=0.0.0.0
 * Serving Flask app "Yippee"
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
├── instance
├── reload
├── setup.py
├── tests
└── Yippee
    ├── db.py
    ├── front.py
    ├── __init__.py
    ├── reload
    ├── schema.sql
    ├── static
    ├── templates
    └── upload.py

__init__.py

from flask import Flask
import os

def create_app(test_config=None):
    # create and configure the app
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_mapping(
        SECRET_KEY='dev',
        DATABASE=os.path.join(app.instance_path, 'WebForTrans.sqlite'),
    )

    if test_config is None:
        # load the instance config, if it exists, when not testing
        app.config.from_pyfile('config.py', silent=True)
    else:
        # load the test config if passed in
        app.config.from_mapping(test_config)

    # ensure the instance folder exists
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    from Yippee import db
    db.init_app(app)

    from Yippee import upload, front
    app.register_blueprint(upload.bp)
    app.register_blueprint(front.bp)
    app.add_url_rule('/', endpoint='index')

    return app
阅读 4.2k
2 个回答

根据 gunicorn 官网的 demo:

$ pip install gunicorn
$ cat myapp.py

def app(environ, start_response):
    data = b"Hello, World!\n"
    start_response("200 OK", [
        ("Content-Type", "text/plain"),
        ("Content-Length", str(len(data)))
    ])
        return iter([data])

$ gunicorn -w 4 myapp:app

这个方法 app 是一个基于 WSGI 协议实现的一个方法, 具体可以看 PEP 333 -- Python Web Server Gateway Interface .

简单说就是输入了命令之后, gunicorn 会去找上面定义的 app, 然后运行 app(), 这个 app 的参数必须是 environstart_response, 别问为什么,协议就是这么规定的,否则无法运行。

你的代码 create_app 这个方法并不是协议的一种实现,所以 gunicorn 无法运行。

为什么要create_app()呢?因为要实例化一个 Flask 对象。现在再来看看 Flask 内部做了什么操作,可以看看 Flask 框架最早版本的代码

Flask 类中有这么两个方法:

def __call__(self, environ, start_response):
    """Shortcut for :attr:`wsgi_app`"""
    return self.wsgi_app(environ, start_response)

def wsgi_app(self, environ, start_response):
    """The actual WSGI application.  This is not implemented in
    `__call__` so that middlewares can be applied:
        app.wsgi_app = MyMiddleware(app.wsgi_app)
    :param environ: a WSGI environment
    :param start_response: a callable accepting a status code,
                           a list of headers and an optional
                           exception context to start the response
    """
    with self.request_context(environ):
        rv = self.preprocess_request()
        if rv is None:
            rv = self.dispatch_request()
        response = self.make_response(rv)
        response = self.process_response(response)
        return response(environ, start_response)

__call__ 魔术方法是让一个对象能够变成可调用的,比如:

In [1]: class Foo(object):
   ...:     def __call__(self):
   ...:         return 'hello world'

In [2]: f = Foo()

In [3]: f()
Out[3]: 'hello world'

当你运行gunicorn -w 4 Yippee:create_app() 的时候,gunicorn 找到了你的 create_app(), 这个返回的是一个 Flask 对象,然后 gunicorn 再去运行这个对象 create_app()() 调用的就是 __call__ 方法,这个方法就是一个 WSGI 协议的实现。

所以就运行起来了。

新手上路,请多包涵

问题已解决 把部署命令改一下
gunicorn "Yippee:create_app()"

有没有人能解释一下这里为什么实例名create_app后要加上括号

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题