Python 多线程和Sqlalchemy

Python 多线程和Sqlalchemy,python,sqlalchemy,Python,Sqlalchemy,我的任务是使用sqlalchemy通过网络更新数据库。我决定使用python的线程模块。目前我使用1个线程,也称为生产者线程,通过队列指示其他线程使用工作单元 生产者线程执行如下操作: def produce(self, last_id): unit = session.query(Request).order_by(Request.id) \ .filter(Request.item_id == None).yield_per(50) self.queue.

我的任务是使用sqlalchemy通过网络更新数据库。我决定使用python的线程模块。目前我使用1个线程,也称为生产者线程,通过队列指示其他线程使用工作单元

生产者线程执行如下操作:

  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)     
消费者线程执行类似的操作:

  def consume(self):
    unit = self.queue.get()
    request = unit
    item = Item.get_item_by_url(request)
    request.item = item
    session.add(request)
    session.flush()
我正在使用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')"
我理解这个例外是因为请求对象是在一个会话(生产者会话)中创建的,而使用者使用另一个作用域会话,因为它们属于另一个线程

我的解决方法是让生产者线程将request.id传递到队列中,而使用者必须调用下面的代码来检索request对象

request = session.query(Request).filter(Request.id == request_id).first()
我不喜欢这个解决方案,因为这涉及到另一个网络呼叫,显然不是最优的

  • 有没有办法避免浪费制作人db调用的结果
  • 是否有一种写入“product”的方法,以便将多个id作为一个工作单元传递到队列中
    欢迎反馈

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

    要分离,请调用会话,传入请求:

    session.expunge(unit)
    
    然后在队列线程中处理它时,通过;将
    load
    标志设置为False,以防止再次往返数据库:

    session.merge(request, load=False)