【问题标题】:SQLAlchemy: How to bind scoped session to requestSQLAlchemy:如何将作用域会话绑定到请求
【发布时间】:2017-03-12 18:00:30
【问题描述】:

我是 sqlalchemy 的新手,似乎我仍然错过了几个基本概念。我想使用 sqlalchemy 处理多线程 Web 应用程序中的数据库交互。

所以我开始

import sqlalchemy
from sqlalchemy                 import create_engine
from sqlalchemy.orm             import sessionmaker, scoped_session

engine          = create_engine('mysql://mydb')
session_factory = sessionmaker( autocommit  = False,
                                autoflush   = False,
                                bind        = engine )
Session         = scoped_session(session_factory)

我使用处理请求的MoinMoin wiki,所以我有一个包含请求的对象macro.request

我现在在某个类中有一个方法,比如说

def do_sth():
    session = Session()
    # use the session to get some data from the db

我在哪里以及如何告诉Session 对象它链接到哪个请求?

阅读Multi-threaded use of SQLAlchemy,它说

ScopedSession 对象默认使用 [threading.local()] 作为存储,以便为所有调用 ScopedSession 注册表的人维护一个 Session,但仅限于单个线程的范围内。在不同线程中调用注册表的调用者会获得该其他线程本地的 Session 实例。

所以“在不同线程中调用注册表的调用者会获得一个该其他线程本地的 Session 实例。”

如果我从未告诉它链接到哪个请求,Session 实例如何是本地的?

【问题讨论】:

    标签: python session sqlalchemy


    【解决方案1】:

    SQLAlchemy documentation

    因此,我们上面的 scoped_session 使用示例(在多个调用中维护相同的 Session 对象)表明,需要有一些进程,以便跨多个线程的多个调用实际上不会获得同一个会话的句柄。我们将此概念称为线程本地存储,这意味着使用一个特殊对象,它将为每个应用程序线程维护一个不同的对象。 Python 通过 threading.local() 结构提供了这一点。

    所以即使我还没有弄清楚如何从给定会话中获取当前线程的pidthreading 模块用于将会话链接到线程。特别是可以查看会话的hash key

    session.hash_key
    

    在问题的示例中测试Session() 在两个调用中提供相同的会话当且仅当两者都在同一个线程中进行。

    因此,总而言之,只要每个请求都由其自己的线程处理,会话就会正确链接到请求。

    【讨论】:

    • 感谢您提供文档链接!
    猜你喜欢
    • 2011-06-15
    • 2012-01-05
    • 2011-09-18
    • 2016-01-02
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多