多线程处理

2024-05-12 00:35:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我的任务是用sqlalchemy通过网络更新数据库。我决定使用python的线程模块。目前我正在使用1个线程,也就是生产者线程,通过一个队列来引导其他线程使用工作单元。在

producer线程执行如下操作:

  def produce(self, last_id):
    unit = session.query(Request).order_by(Request.id) \
        .filter(Request.item_id == None).yield_per(50)
    self.queue.put(unit, True, Master.THREAD_TIMEOUT)     

当使用者线程执行类似的操作时:

^{pr2}$

我正在使用sqlalchemy的作用域会话:

session = scoped_session(sessionmaker(autocommit=True, autoflush=True, bind=engine))

但是,我得到了例外

"sqlalchemy.exc.InvalidRequestError: Object FOO is already attached to session '1234' (this is '5678')"

我知道这个异常是因为请求对象是在一个会话(生产者会话)中创建的,而消费者使用另一个作用域的会话,因为它们属于另一个线程。在

我的工作就是让我的制作人请求.id当消费者必须调用下面的代码来检索请求对象时。在

request = session.query(Request).filter(Request.id == request_id).first()

我不喜欢这个解决方案,因为这涉及到另一个网络呼叫,显然不是最佳方案。在

  1. 有没有办法避免浪费制作人的数据库调用的结果?在
  2. 有没有一种方法可以编写“product”,以便将多个id作为一个工作单元传递到队列中?在

欢迎反馈!在


Tags: self网络id数据库truesqlalchemy队列request
1条回答
网友
1楼 · 发布于 2024-05-12 00:35:18

在将Request实例放入队列之前,需要将其与主线程会话分离,然后在再次从队列中取出时将其附加到队列处理线程会话。在

要分离,请在会话上调用^{},传递请求:

session.expunge(unit)

然后在队列线程中处理它时,通过merging重新附加它;将load标志设置为False以防止再次往返数据库:

^{pr2}$

相关问题 更多 >