Сохранение состояния в приложении mod_wsgi Flask

#python #flask #mod-wsgi

#python #flask #mod-wsgi

Вопрос:

У меня есть приложение 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 , но это не так. Есть ли лучший, более питонический, более похожий на Flask способ сделать это?

Ответ №1:

Я полагаю, это будет зависеть от базы данных (и ORM), с которой вы используете. Если вы используете SQLAlchemy или flask-sqlalchemy (что я настоятельно рекомендую вам сделать), вы обычно определяете одну глобальную переменную для подключения к базе данных. Обычно это настраивается в init_app() -function . Если вы посмотрите на код настройки приложения, вы увидите, что довольно часто основным объектом приложения 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)   
  

Ответ №2:

Что касается совместного использования состояния между потоками wsgi, существует директива, которую вы можете поместить в конфигурацию виртуального хоста apache, которая позволяет им выполняться в одном контексте.

Директива WSGIApplicationGroup может использоваться для указания, к какой группе приложений принадлежит приложение WSGI или набор приложений WSGI. Все приложения WSGI в одной и той же группе приложений будут выполняться в контексте одного и того же субинтерпретатора Python процесса, обрабатывающего запрос.

Обратите внимание, что это для потоков внутри процесса, а не между процессами.