【问题标题】:Sqlalchemy scoped_session and "already attached" errorsSqlalchemy scoped_session 和“已附加”错误
【发布时间】:2016-05-10 05:37:21
【问题描述】:

我在这里的第一篇文章。我正在尝试对以前的单线程数据库应用程序(postgresql、python2.7、sqlalchemy)进行多线程处理。

我已按照在线说明更改了我的会话处理程序,如下所示。这是在启动任何工作程序之前在控制线程中完成的:

config.engine = create_engine("postgresql://foo:foobar@localhost/foo", echo=False)
config.session_factory = sessionmaker(bind=config.engine)
config.Session = scoped_session(config.session_factory)

我从其他线程得到的错误消息是这样的。当一个线程启动时,它会创建一个作用域会话的新实例,并尝试将它从控制线程接收到的对象(self.channel)添加到它的会话上下文中:

self.session = config.Session()
self.session.add(self.channel)

我从工作线程得到的错误是这样的:

InvalidRequestError: Object '<YChannel at 0x7ff3bab09490>' is already attached to session '1' (this is '3')

我做错了什么?这些是我在会话不是范围会话时遇到的错误,但我从文档中了解到,一旦我切换到范围会话,这些错误就会消失。

理查德

【问题讨论】:

  • 问题在于您在线程之间共享对象,这些线程具有不同的会话。如果您希望能够做到这一点,您需要从旧会话中分离实例,然后将其重新附加到新会话。
  • 好的。那我该如何解决呢?我有需要在不同线程中监视和操作的表。有一种内置机制可以确保不同的线程不会修改相同的对象,但所有线程的存储都在同一组表中。
  • 您需要先从会话中分离一个实例,然后再将其发送到另一个线程,然后在接收线程中重新附加它。

标签: python multithreading sqlalchemy


【解决方案1】:

正如 universo 在 cmets 中所说,您正在尝试在多个会话/线程之间共享对象。您的 channel 对象是在主线程中创建的。当您启动执行程序时,Thread 1 会创建一个新会话并将 channel 对象添加到它的会话中。现在,当执行 Thread 2 时,它会创建自己的会话并尝试将 channel 对象再次添加到其会话中。由于无法跨会话共享对象,因此您遇到了异常。

要解决这个问题,这实际上取决于您想要实现的目标。如果您只有一个 channel 对象,为什么还要使用多个线程和会话。如果有多个通道对象,您可以考虑在线程本身中创建对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-26
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 2019-06-22
    • 2020-11-23
    • 2013-11-09
    相关资源
    最近更新 更多