在mod_wsgi的Flask应用中保持状态
我有一个Flask应用程序,它在mod_wsgi下运行,并且连接了一个数据库。这个应用程序有多个进程在运行(每个进程只有一个线程),每个进程都有一个数据库连接。
现在我的代码大概是这样的:
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
来处理,但它不是。有没有更好、更符合Python风格、更符合Flask风格的方法来做到这一点呢?
2 个回答
关于在wsgi线程之间共享状态,有一个指令可以放在apache的虚拟主机配置中,这样它们就可以在同一个上下文中执行。
WSGIApplicationGroup指令可以用来指定一个WSGI应用程序或一组WSGI应用程序属于哪个应用组。所有在同一个应用组中的WSGI应用程序都会在处理请求的进程的同一个Python子解释器的上下文中执行。
请注意,这个是针对同一个进程中的线程,而不是不同进程之间。
这主要取决于你使用的数据库和ORM(对象关系映射工具)。如果你使用的是SQLAlchemy或者flask-sqlalchemy
(我强烈建议你使用这个),通常你会定义一个全局变量来连接数据库。这个连接一般是在一个叫做init_app()
的函数中设置的。如果你查看应用程序的设置代码,你会发现主flask应用对象通常是一个全局变量app
。而数据库对象通常也是一个全局变量db
,它通常和app
一起被导入到应用的其他部分。
你应该查看一下应用上下文和请求上下文的文档,特别是上下文的局部性,它解释了这些是如何工作的。基本上,上下文在请求之间(也就是线程之间)是不会共享的,所以不会出现竞争条件和问题。
另外,在你的情况下,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)