我有一个在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的方式吗?
答案 0 :(得分:1)
我想这取决于您使用的数据库(和ORM)。如果您正在使用SQLAlchemy或flask-sqlalchemy
(我强烈建议您这样做),您通常会为数据库连接定义一个全局变量。这通常在init_app()
- 函数中设置。如果查看应用程序设置代码,您会发现主要的烧瓶应用程序对象通常是全局变量app
。通常,您会将数据库对象视为全局变量db
,它通常与app
一起导入到应用程序的其他部分。
您应该查看application和request - 上下文文档,尤其是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子解释器的上下文中执行。
请注意,这适用于流程中的线程,而不是流程之间的线程。