【问题标题】:SQLAlchemy in multithread scoped_session多线程 scoped_session 中的 SQLAlchemy
【发布时间】:2021-05-15 00:35:15
【问题描述】:

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

线程 1 启动所有 SQLAlchemy 对象(Engine、Models、scoped_session 等)

线程 2 然后尝试使用 scoped_session 对象查询数据库。不幸的是,从线程 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())

这是带有错误消息的输出:

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>]

由于某种原因,该表不存在。我已经阅读并重新阅读了文档以及互联网上的多个帖子,并且对于上述确切情况,似乎存在 scoped_session。有人可以启发我吗?

【问题讨论】:

    标签: python sqlalchemy python-multithreading


    【解决方案1】:

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

    【讨论】:

    • 感谢您的评论,对未来的观众来说,是的,内存数据库至少不支持范围会话,至少我使用的版本。
    【解决方案2】:

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

    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()
    

    请记住,会话必须在请求结束时手动销毁!您将在using-custom-created-scopes 下找到更多信息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-29
      • 2022-11-17
      • 1970-01-01
      • 1970-01-01
      • 2011-09-25
      • 1970-01-01
      • 2016-12-31
      • 2010-11-24
      相关资源
      最近更新 更多