Python SAWarning:至少已存在一个作用域会话

Python SAWarning:至少已存在一个作用域会话,python,session,sqlalchemy,pyramid,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)) engin

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

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

DBSessionTask = scoped_session(sessionmaker(extension=ZopeTransactionExtension(), expire_on_commit=False))
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)
配置会话(在Pyramid应用程序的主
\uuuuu init\uuuuuuuu.py
中):

会话将用于两种不同类别的对象(
DBSessionTask
用于应用程序范围内设置的长时间运行的监控对象,
DBSession
用于web应用程序“数据”对象的典型范围会话)

我得到一个警告:

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,但为什么会出现问题?

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

如果您想在Pyramid+SQLAlchemy中使用多个会话,您应该显式地管理它们,而不是依赖作用域会话。作用域会话sessionmaker希望每个线程创建一个会话,因此您的问题就出现了。许多金字塔开发人员都喜欢这样做,因为这符合金字塔的哲学,即通过请求和上下文对象传递所有内容。我的首选是制作一个db引擎组件,该组件具有获取和关闭会话的方法,并通过configurator注册该组件。然后我有一个定制的请求工厂,它在请求开始时创建db会话,并在请求结束时提交或回滚它。通过在configurator部分注册请求生命周期回调,您也可以在没有自定义请求工厂的情况下执行相同的操作。下面是一个从烹饪书中摘取的执行上述操作的示例,您可以很容易地将其应用于多个发动机:


你为什么不想使用1
作用域会话
?@matino:因为一个作用域会话是常规的金字塔会话,我不想像更改它的expire\u on\u commit设置那样对它进行破坏。同时,我需要另一个会话将此设置设置为True。我在本地运行测试时收到此警告-是否有“一个明显的”解决方法?测试数据库是一个临时SQLIte文件。
# __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)