Preserving state in mod_wsgi Flask application

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-01 12:50:09

问题


I have a Flask application running under mod_wsgi that makes a connection to a database. There are multiple processes running this application (only one thread per process) and one database connection for each of these processes.

Currently I have something like this:

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

Now the use of global variables here doesn't feel very good. If the app were a class, I could use self.db, but it's not. Is there a better, more Pythonic, more Flask-esque way to do this?


回答1:


This I suppose will depend on the database (and ORM) you're using with. If you're using SQLAlchemy or flask-sqlalchemy, (which I highly suggest you to do), you will usually define a single global variable for the database connection. This is usually set up in an init_app()-function. If you look at the application set up code, you'll see that quite often the main flask application object is a global variable app. Very often you'll find the database object as a global variable db which is often imported together with the app to other parts of the application.

You should look at the application and request-context documentation and especially the locality of the context, which explains how this works. Basically the context is never shared between requests (and thus threads), so there should be no race conditions and no problems.

Also, the global keyword in your case is not necessary. The point is that you will never really change the content of the variable db. It's an object which controls the database connection and you only call the methods it offers. The global keyword is necessary when you want to mutate the contents of the variable, by assigning a new value to it.

So, I would refactor the setup() as follows (and preferrably put this an __init__.py so it's nicely importable)

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()

And then in the mod_wsgi.py

from myapp import app

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



回答2:


Regarding sharing state between wsgi threads, there is a directive you can put in the apache virtual host configuration that allows them to be executed in the same context.

The WSGIApplicationGroup directive can be used to specify which application group a WSGI application or set of WSGI applications belongs to. All WSGI applications within the same application group will execute within the context of the same Python sub interpreter of the process handling the request.

Note that this is for threads within a process, not between processes.



来源:https://stackoverflow.com/questions/24429271/preserving-state-in-mod-wsgi-flask-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!