Подтвердить что ты не робот

Каков рекомендуемый шаблон использования scoped_session в многопоточном sqlalchemy webapp?

Я пишу приложение с python и sqlalchemy-0.7. Он начинается с инициализации orm (sqlalchemy orm) с объявлением, а затем начинается многопоточный веб-сервер. В настоящее время я использую web.py для быстрого прототипирования, но это может измениться в будущем. Я также добавлю другие "потоки" для запланированных заданий и т.д., Возможно, используя другие потоки python.

Из документации по SA Я понимаю, что мне нужно использовать scoped_session() для получения потока-локального сеанса, поэтому мое приложение web.py должно выглядеть примерно так:

import web
from myapp.model import Session  # scoped_session(sessionmaker(bind=engine))
from myapp.model import This, That, AndSoOn
urls = blah...
app  = web.application(urls, globals())

class index:
    def GET(self):
        s = Session()
        # get stuff done
        Session().remove()
        return(stuff)

class foo:
    def GET(self):
        s = Session()
        # get stuff done
        Session().remove()
        return(stuff)

Это правильный способ обработки сеанса?

Насколько я понимаю, я должен получить scoped_session для каждого метода, поскольку он даст мне локальный сеанс потока, который я не смог получить заранее (например, на уровне модуля).

Кроме того, я должен вызывать .remove() или .commit() или что-то вроде них на каждом конце метода, иначе сеанс будет по-прежнему содержать Persistent, и я не смог бы запросить/получить доступ к тем же объектам в других потоках?

Если этот шаблон правильный, возможно, его можно улучшить, написав его только один раз, возможно, используя декоратор? Такой декоратор может получить сеанс, вызвать метод, а затем убедиться, что он правильно настроил сеанс. Как это пройдет сеанс с украшенной функцией?

4b9b3361

Ответ 1

Да, это правильный путь.

Пример:

Flask микрофрейм с Flask-sqlalchemy расширение делает то, что вы описали. Он также делает .remove() автоматически в конце каждого HTTP-запроса (функции "просмотра" ), поэтому сеанс освобождается текущим потоком. Вызов просто .commit() недостаточно, вы должны использовать .remove().

Если вы не используете представления Flask, я обычно использую оператор "with":

@contextmanager
def get_db_session():
    try:
        yield session
    finally:
        session.remove()

with get_db_session():
    # do something

Вы можете создать аналогичный декоратор.

Scoped session создает пул соединений СУБД, поэтому этот подход будет быстрее, чем открытие/закрытие сессии при каждом HTTP-запросе. Он также отлично работает с зелеными (gevent или eventlet).

Ответ 2

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

Вы должны вызвать s.commit(), чтобы сделать ожидающие объекты постоянными, т.е. сохранить изменения в базе данных.

Вы также можете закрыть сеанс, вызвав s.close().