为什么Flask的app.config.from_object()与gunicorn的行为有所不同?

时间:2016-06-07 09:35:10

标签: python flask gunicorn

我正在使用带有virtualenv的Flask,我的演示Flask应用程序的结构如下:

app/
    hello.py
config/
    settings.py
venv/
    virtualenv files

hello.py

的内容
from flask import Flask


def create_app():
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_object("config.settings")

    @app.route('/')
    def index():
        return app.config["HELLO"]

    return app

if __name__ == "__main__":
    app = create_app()
    app.run()

settings.py只包含2个值

DEBUG = True
HELLO = "Hello there from /config !"

我可以使用gunicorn -b 0.0.0.0:9000 --access-logfile - "app.hello:create_app()"使用gunicorn成功运行此功能,它可以正常运行。

但是,从root运行python app/hello.py会导致错误ImportError: No module named 'config'。当以这种方式执行时,似乎烧瓶无法找到配置目录。

我可以在config内移动app目录,但这样做会导致gunicorn错误。难道两种方式都不可能“正常工作”吗?更重要的是,为什么以及发生了什么?

1 个答案:

答案 0 :(得分:2)

不是最优雅但仍然完美的解决方案:

from os.path import abspath, join
from flask import Flask


def create_app():
    app = Flask(__name__, instance_relative_config=True)
    config_file_path = abspath(
        join(app.instance_path, '../config/settings.py')
    )
    app.config.from_pyfile(config_file_path)

    @app.route('/')
    def index():
        return app.config["HELLO"]

    return app


if __name__ == "__main__":
    app = create_app()
    app.run()

考虑评论后增加。为了让Flask正确导入config.settings,app根目录的路径必须位于sys.path内。可以通过在原始脚本中添加一行来轻松实现:

sys.path.insert(0, os.getcwd())

所以最后的hello.py看起来像是:

import os
import sys
from flask import Flask


def create_app():
    app = Flask(__name__, instance_relative_config=True)
    sys.path.insert(0, os.getcwd())
    app.config.from_object("config.settings")

    @app.route('/')
    def index():
        return app.config["HELLO"]

    return app


if __name__ == "__main__":
    app = create_app()
    app.run()

更加防弹的解决方案是

app_root_path = os.path.abspath(
    os.path.join(app.instance_path, '..')
)
sys.path.insert(0, app_root_path)

这样我们就不依赖于os.getcwd()返回的内容:它并不总是必须返回应用程序根路径。