Python 多线程作用域_会话中的SQLAlchemy

Python 多线程作用域_会话中的SQLAlchemy,python,sqlalchemy,python-multithreading,Python,Sqlalchemy,Python Multithreading,我试图在多线程环境中使用SQLAlchemy,但遇到了一些奇怪的错误。情况如下: 线程1启动所有SQLAlchemy对象(引擎、模型、作用域_会话等) 然后,线程2尝试使用作用域_会话对象查询数据库。不幸的是,从线程2抛出错误 我创建了一个简单的测试用例来说明我试图实现的目标: import sqlalchemy from sqlalchemy import Column, Integer, String, Boolean, desc, asc, func from sqlalchemy im

我试图在多线程环境中使用SQLAlchemy,但遇到了一些奇怪的错误。情况如下:

线程1启动所有SQLAlchemy对象(引擎、模型、作用域_会话等)

然后,线程2尝试使用作用域_会话对象查询数据库。不幸的是,从线程2抛出错误

我创建了一个简单的测试用例来说明我试图实现的目标:

import sqlalchemy
from sqlalchemy import Column, Integer, String, Boolean, desc, asc, func

from sqlalchemy import create_engine
sqlEngine = create_engine('sqlite:///:memory:',echo=False)
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class SimpleTable(Base):
    __tablename__ = 'SimpleTable'

    orderID = Column(Integer, primary_key=True)
    field = Column(Integer)

    def __repr__(self):
    return "<Simple Table: %s>" % self.field

session_factory = sessionmaker(bind=sqlEngine)
Session = scoped_session(session_factory)
Base.metadata.create_all(sqlEngine)

for i in xrange(10):
    var = SimpleTable(field=10)
    Session.add(var)

Session.query(SimpleTable).all()
Session.commit()

from threading import Thread

class TestThread(Thread):

    def run(self):
    print "Running test thread..."
    try:
        print 'Grabbing data from thread:'+str(Session.query(SimpleTable).all())
    except BaseException as e:
        print e
    print "Done running test thread..."

TestThread().start()

print 'Grabbing data outside thread:'+str(Session.query(SimpleTable).all())
导入sqlalchemy
从sqlalchemy导入列、整数、字符串、布尔值、desc、asc、func
从sqlalchemy导入创建引擎
sqlEngine=create_引擎('sqlite://:memory:',echo=False)
从sqlalchemy.orm导入sessionmaker,作用域_会话
从sqlalchemy.ext.declarative导入声明性基础
Base=声明性_Base()
类SimpleTable(基):
__tablename_uu='SimpleTable'
orderID=列(整数,主键=True)
字段=列(整数)
定义报告(自我):
返回“%self.field”
session\u factory=sessionmaker(bind=sqlEngine)
会话=作用域会话(会话工厂)
Base.metadata.create_all(sqlEngine)
对于X范围内的i(10):
var=SimpleTable(字段=10)
Session.add(var)
Session.query(SimpleTable).all()
Session.commit()
从线程导入线程
类TestThread(线程):
def运行(自):
打印“正在运行测试线程…”
尝试:
打印“从线程抓取数据:”+str(Session.query(SimpleTable).all())
除BaseException作为e外:
打印e
打印“完成运行测试线程…”
TestThread().start()
打印“抓取线程外的数据:”+str(Session.query(SimpleTable).all())
以下是带有错误消息的输出:

Running test thread...
(OperationalError) no such table: SimpleTable u'SELECT "SimpleTable"."orderID" AS "SimpleTable_orderID", "SimpleTable".field AS "SimpleTable_field" \nFROM "SimpleTable"' ()
Done running test thread...
Grabbing data outside thread:[<Simple Table: 10>, <Simple Table: 10>, <Simple Table: 10>, <Simple Table: 10>, <Simple Table: 10>, <Simple Table: 10>, <Simple Table: 10>, <Simple Table: 10>, <Simple Table: 10>, <Simple Table: 10>]
正在运行测试线程。。。
(操作错误)没有这样的表:SimpleTable u'从“SimpleTable”中选择“SimpleTable”。“orderID”为“SimpleTable\u orderID”,“SimpleTable.”字段为“SimpleTable\u字段”()
已完成运行测试线程。。。
正在获取线程外的数据:[,,,,,,]

由于某种原因,该表不存在。我已经阅读并重新阅读了文档以及互联网上的多篇帖子,似乎存在针对上述确切案例的scoped_会话。有人能启发我吗

我也遇到过同样的情况。我怀疑“内存中”db不支持作用域_会话。当我切换到普通的基于文件的数据库时,问题就消失了。

只要手动将会话实例绑定到请求,而不是直接绑定到线程,就可以使用scoped_会话工厂。检查是否存在非必需的scopefunc参数。它应该需要一些散列对象。当使用带有哈希请求的web框架时,您可以直接将id作为值。如果不是的话,就把它包装成hashable对象

from my_web_framework import get_current_request, on_request_end
from sqlalchemy.orm import scoped_session, sessionmaker

Session = scoped_session(sessionmaker(bind=some_engine), scopefunc=get_current_request)

@on_request_end
def remove_session(req):
    Session.remove()

请记住,会话必须在请求结束时手动销毁!您将在

下找到更多信息,谢谢您的评论,对未来的观众来说,是的,内存中的db不支持作用域会话,至少是我使用的版本。