【问题标题】:Issues with scoped_session in sqlalchemy - how does it work?sqlalchemy 中 scoped_session 的问题 - 它是如何工作的?
【发布时间】:2010-11-24 02:22:56
【问题描述】:

我不太确定 scoped_session 是如何工作的,除了它似乎是一个隐藏多个真实会话的包装器,将它们分开以处理不同的请求。它对线程局部变量执行此操作吗?

反正麻烦如下:

S = elixir.session # = scoped_session(...)
f = Foo(bar=1)
S.add(f) # ERROR, f is already attached to session (different session)

不确定 f 如何在不同的会话中结束,我之前没有遇到过问题。在其他地方,我的代码看起来就像那样,但实际上可以工作。你可以想象,我觉得这很令人困惑。

我只是在这里什么都不知道,f 似乎被神奇地添加到构造函数中的会话中,但我似乎没有对它使用的会话的任何引用。为什么它会在不同的会话中结束?我怎样才能让它在正确的会话中结束?这个 scoped_session 是如何工作的?它有时似乎有效,有时却无效。

我肯定很困惑。

【问题讨论】:

    标签: python sqlalchemy python-elixir


    【解决方案1】:

    事实证明,elixir 在创建的映射器上设置了 save-on-init=True。这可以通过以下方式禁用:

    using_mapper_options(save_on_init=False)
    

    这解决了问题。感谢 #sqlalchemy 上的 stepz 立即弄清楚发生了什么。虽然我仍然很好奇 scoped_session 是如何真正起作用的,但如果有人回答了这个问题,他们会因为回答这个问题而获得荣誉。

    【讨论】:

      【解决方案2】:

      作用域会话创建一个代理对象,该对象保留(默认情况下)每个线程会话对象的注册表,该对象是从传递的会话工厂按需创建的。当您访问诸如ScopedSession.add 之类的会话方法时,它会找到与当前线程对应的会话并返回绑定到该会话的add 方法。可以使用ScopedSession.remove() 方法删除活动会话。

      ScopedSession 有一些方便的方法,一个是query_property,它创建一个属性,该属性返回一个查询对象,该对象绑定到创建它的作用域会话和访问它的类。另一个是ScopedSession.mapper,它添加了一个默认的__init__(**kwargs) 构造函数,默认情况下将创建的对象添加到创建映射器的作用域会话中。此行为可以由映射器的 save_on_init 关键字参数控制。 ScopedSession.mapper 已被弃用,因为正是问题中的问题。这是 Python “显式优于隐式”哲学真正适用的一种情况。不幸的是,Elixir 仍然默认使用ScopedSession.mapper

      【讨论】:

        猜你喜欢
        • 2022-11-17
        • 1970-01-01
        • 1970-01-01
        • 2011-09-25
        • 1970-01-01
        • 1970-01-01
        • 2019-11-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多