我有一种情况,其中几个搜索过程并行化为不同的线程。每个线程获取相同的pymongo.cursor.Cusor
对象以查看其结果,但每个线程执行不同的处理。我创建了一个演示程序,如下所示:
class SearchProcedure(Thread):
weight = 0.1
def __init__(self,weight=None):
if weight:
self.weight = float(weight)
Thread.__init__(self)
def start(self,query):
self.query = query
Thread.start(self)
def run(self):
if hasattr(self,'places'):
for p in self.places.values():
print p.name
if hasattr(self,'posts'):
for s in self.posts.values():
s.rewind()
print [(sh['name'],sh['description']) for sh in s]
def attach_eligible(self,queue,**kwargs):
self.queue = queue
for (name,value) in kwargs.items():
setattr(self,name,value)
attach_eligible
方法是将位置和帖子的属性添加到过程对象的位置。同样,posts
属性是一组可以迭代的mongo游标。我在运行结果之前使用rewind
将光标重置为原始状态,如果另一个线程已经解开它。我们的想法是每个线程将使用不同的标准来搜索对象,然后将其结果发送到queue
属性,以便在调用/实例化范围中使用。
第一个线程运行良好,但所有后续线程利用光标输出以下错误:
File "/usr/local/lib/python2.7/dist-packages/pymongo/cursor.py", line 668, in __send_message
assert response["starting_from"] == self.__retrieved
AssertionError
看起来,倒退没有效果。这是因为游标是通过引用传入的吗?它们是否也需要包含在队列中以保持锁定状态?用mongo游标甚至可以做这样的事情吗?如果可以的话会很好,因为它会使搜索条件的处理更加高效,同时执行它。
答案 0 :(得分:1)
除非经过专门设计允许,否则您无法在线程之间自由共享任何更改状态的对象。 pymongo cursor
不是为此设计的。
您可以做的是克隆光标,然后为每个线程提供自己的克隆光标副本。请参阅cursor.clone
。
答案 1 :(得分:0)
详细介绍@JohnnyHK's answer:
根据this answer,光标位于服务器端。完成的任何递增操作都反映在服务器端,因此在第二个线程中复制游标(以某种方式)就像在第二个线程中复制URL,而不是对象/对象列表。 即光标是指向数据库中数据的指针,除非在服务器端进行复制,否则不能复制。因此,您应该使用提及的cursor.clone。