SAWarning:至少有一个范围的会话已经存在

时间:2015-08-07 11:39:16

标签: python session sqlalchemy pyramid

我有目的地定义了2个不同的引擎(使用相同的DB URL),用于2个具有不同配置的会话,Pyramid的model.py

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))

DBSessionTask = scoped_session(sessionmaker(extension=ZopeTransactionExtension(), expire_on_commit=False))

配置会话(在Pyramid应用程序的主__init__.py中):

engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind=engine)
Base.metadata.bind = engine

engine_task = engine_from_config(settings, 'sqlalchemy.')
DBSessionTask.configure(bind=engine_task)

会话旨在用于2个不同类别的对象(DBSessionTask用于在应用程序范围设置中保存的长期监督对象,DBSession用于“数据”对象上的典型范围会话一个网络应用程序)。

我收到了警告:

sqlalchemy\orm\scoping.py:99: SAWarning: At least one scoped session is already present.  configure() can not affect sessions that have already been created.
  warn('At least one scoped session is already present. '

这是两个不同的引擎,为什么SQA会警告我呢?他们当然使用相同的DB url,但为什么这应该是一个问题?

2 个答案:

答案 0 :(得分:1)

如果要在Pyramid + SQLAlchemy中使用多个会话,则应明确管理它们,而不是依赖范围会话。范围会话sessionmaker期望每个线程创建一个会话,因此您的问题。许多金字塔开发者更喜欢这样做作为一般规则,因为它非常适合通过请求和上下文对象传递所有内容的金字塔哲学。我的首选是创建一个db引擎组件,它具有获取和关闭会话的方法,并通过配置器注册该组件。然后我有一个自定义请求工厂,它在请求开始时创建数据库会话,并在最后提交或回滚它。通过在配置程序部分注册请求生命周期回调,您也可以在没有自定义请求工厂的情况下执行相同的操作。以下是从烹饪书中获取上述内容的示例,您可以轻松地适应多个引擎:

http://pyramid-cookbook.readthedocs.org/en/latest/database/sqlalchemy.html

# __init__.py

from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from sqlalchemy.orm import sessionmaker

def db(request):
    maker = request.registry.dbmaker
    session = maker()

    def cleanup(request):
        if request.exception is not None:
            session.rollback()
        else:
            session.commit()
        session.close()
    request.add_finished_callback(cleanup)

    return session


def main(global_config, **settings):
    config = Configurator(settings=settings)
    engine = engine_from_config(settings, prefix='sqlalchemy.')
    config.registry.dbmaker = sessionmaker(bind=engine)
    config.add_request_method(db, reify=True)

答案 1 :(得分:0)

您应该使用一个范围会话将模型绑定到不同的数据库引擎。