2

我有一种情况,其中几个搜索过程被并行化到不同的线程中。每个线程获取相同的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 游标做这样的事情吗?如果可以的话,那就太好了,因为它会使搜索条件的处理性能更高,以使其同时执行。

4

2 回答 2

2

你不能在线程之间自由地共享任何改变状态的对象,除非它是专门设计来允许的。pymongocursor不是为此而设计的。

您可以做的是克隆游标,然后为每个线程提供其自己的游标克隆副本。见cursor.clone

于 2012-10-23T16:09:52.593 回答
0

详细说明@JohnnyHK 的回答

根据this answer,光标位于服务器端。所做的任何递增操作都会反映在服务器端,因此在第二个线程中复制光标(在某种程度上)就像在第二个线程中复制 URL,而不是对象/对象列表。即游标是指向数据库中数据的指针,不能被复制,除非在服务器端复制它。因此,您应该使用前面提到的 cursor.clone。

于 2020-09-03T08:06:50.263 回答