在mod_wsgi Flask应用程序中保留状态

时间:2014-06-26 11:25:52

标签: python flask mod-wsgi

我有一个在mod_wsgi下运行的Flask应用程序,它与数据库建立了连接。有多个进程在运行此应用程序(每个进程只有一个线程),并且每个进程都有一个数据库连接。

目前我有这样的事情:

myapp_wsgi.py

import myapp
app = myapp.setup()

def application(environ, start_response):
    return app(environ, start_response)

myapp.py

from flask import Flask

app = Flask(__name__)

db = None

def setup():
    global db
    db = get_db()
    # Other setup
    return app

@app.route("/")
def index():
    data = db.get_data()
    return data

现在使用全局变量并不是很好。如果应用是一个类,我可以使用self.db,但事实并非如此。有更好的,更Pythonic,更像Flask的方式吗?

2 个答案:

答案 0 :(得分:1)

我想这取决于您使用的数据库(和ORM)。如果您正在使用SQLAlchemy或flask-sqlalchemy(我强烈建议您这样做),您通常会为数据库连接定义一个全局变量。这通常在init_app() - 函数中设置。如果查看应用程序设置代码,您会发现主要的烧瓶应用程序对象通常是全局变量app。通常,您会将数据库对象视为全局变量db,它通常与app一起导入到应用程序的其他部分。

您应该查看applicationrequest - 上下文文档,尤其是locality of the context,它解释了这是如何工作的。基本上,请求(以及线程)之间永远不会共享上下文,因此不存在竞争条件且没有问题。

此外,您的案例中的global关键字不是必需的。关键是你永远不会真正改变变量db的内容。它是一个控制数据库连接的对象,您只调用它提供的方法。如果您希望通过为其指定新值来变异变量的内容,则global关键字是必需的。

所以,我会按如下方式重构setup()(并且最好将其设为__init__.py,以便它可以很好地导入)

from flask import Flask

def setup():
    app = Flask(__name__)
    db = get_db() #This is a local variable now
    # whatever else needs to be done
    return app, db

app, db = setup()

然后在mod_wsgi.py

from myapp import app

def application(environ, start_response):
    return app(environ, start_response)   

答案 1 :(得分:0)

关于在wsgi线程之间共享状态,有一个指令可以放在apache虚拟主机配置中,允许它们在同一个上下文中执行。

  

WSGIApplicationGroup指令可用于指定WSGI应用程序或WSGI应用程序集所属的应用程序组。同一应用程序组中的所有WSGI应用程序都将在处理请求的进程的同一Python子解释器的上下文中执行。

请注意,这适用于流程中的线程,而不是流程之间的线程。