Python 多线程和Sqlalchemy
我的任务是使用sqlalchemy通过网络更新数据库。我决定使用python的线程模块。目前我使用1个线程,也称为生产者线程,通过队列指示其他线程使用工作单元 生产者线程执行如下操作: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.
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()
我不喜欢这个解决方案,因为这涉及到另一个网络呼叫,显然不是最优的
欢迎反馈 在将
请求
实例放入队列之前,需要将其从主线程会话中分离,然后在再次从队列中取出时将其附加到队列处理线程会话
要分离,请调用会话,传入请求:
session.expunge(unit)
然后在队列线程中处理它时,通过;将load
标志设置为False,以防止再次往返数据库:
session.merge(request, load=False)