1

我正在运行 nginx + gunicorn + flask

我的 nginx 配置如下所示:

...

        proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header            Host $http_host;
        proxy_set_header            Stage "development";

        proxy_redirect off;

...

我的烧瓶应用程序如下所示:

from flask import Flask, request

from werkzeug.contrib.fixers import ProxyFix

app = Flask(__name__)

# configuration settings

if request.headers.get('Stage') == 'production':
    app.config.from_object('config.production_config')
else:
    app.config.from_object('config.development_config')

@app.route('/')
def index():
    return "hello"

app.wsgi_app = ProxyFix(app.wsgi_app)

然而,

这似乎行不通。

我得到一个:RuntimeError:在请求上下文之外工作

我的 nginx 已设置好,因此我可以拥有一个开发/生产环境,但我希望能够说这个“服务器位置”是一个开发环境,并且我希望 Flask 使用适当的配置。

4

2 回答 2

4

应用程序配置适用于整个应用程序,而请求标头仅适用于一个请求。同一个应用程序通常处理许多请求。因此,您不能根据请求标头设置配置。

当没有请求到达应用程序时,您的模块级别的代码在服务器启动时执行,因此没有当前请求。这就是“在请求上下文之外工作”消息的含义。

您正在尝试做的事情(prod 与 dev 配置)最好使用启动 gunicorn 服务器的脚本中的环境变量来完成。如果您同时想要两者,最简单的方法是运行两个 gunicorn 服务器。

或者,创建两个应用程序对象,在同一个进程中运行它们,并使用类似于这些的 WSGI 中间件进行调度:http: //flask.pocoo.org/docs/patterns/appdispatch/

于 2012-08-03T09:00:59.507 回答
1

这有点老了,但我想补充一下我们是如何用烧瓶完成这个的。其中大部分改编自http://flask.pocoo.org/docs/config/

在我们的 config.py 中,我们定义了多个类(每个环境一个):

class Config(object):
    FOO = 1
    BAR = 2

class Development(Config):
    BAR = 3

然后在我们的每个应用程序节点中,我们在 gunicorn 初始化脚本中设置一个环境变量(对我们来说,这存在于主管配置中,但它不是必须的)。

APPLICATION_ENV='Development'

然后在初始化期间在烧瓶应用程序中(仅在服务器启动时运行,而不是在请求上下文中):

try:
    env = os.environ['APPLICATION_ENV']
except KeyError as e:
    logging.error('Unknown environment key, defaulting to Development')
    env = 'Development'
    app.config.from_object('config.%s' % env)

现在 app.config['BAR'] 将是 3。

我们还希望支持本地配置文件(例如,在开发人员机器上或从厨师直接部署到机器而不存储在 git 中的密码)。为此,我们在上面进行了扩展,还加载了基于 app.config['LOCAL_CONFIG'] 参数的本地配置。

class Development(Config):
    BAR = 3
    LOCAL_CONFIG = '/etc/localConfig.py'

然后在 /etc/localConfig.py

BAR = 4

在上面的代码加载环境的初始 app.config 之后,再次在我们的应用程序初始化代码中:

if 'LOCAL_CONFIG' in app.config:
    #try to load the local configuration overrides
    if app.config.from_pyfile(app.config['LOCAL_CONFIG'], silent=True):
        logging.info('Loaded local config file at %s' % app.config['LOCAL_CONFIG'])
    else:
        logging.warning('Failed to load local config file at %s - does it exist?' % app.config['LOCAL_CONFIG'])

此时 app.config['BAR'] 为 4。

这并不完美,因为如果您的配置中有字典,您将只能覆盖整个字典,而不是其中的键。它确实完成了我们需要的大部分工作。

于 2013-01-05T14:17:57.990 回答