Python 多线程作用域_会话中的SQLAlchemy
我试图在多线程环境中使用SQLAlchemy,但遇到了一些奇怪的错误。情况如下: 线程1启动所有SQLAlchemy对象(引擎、模型、作用域_会话等) 然后,线程2尝试使用作用域_会话对象查询数据库。不幸的是,从线程2抛出错误 我创建了一个简单的测试用例来说明我试图实现的目标: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
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不支持作用域会话,至少是我使用的版本。