2012-10-23 75 views
1

我有一種情況,幾個搜索過程並行化到不同的線程中。每個線程獲取相同的pymongo.cursor.Cusor對象來查看其結果,但每個線程執行不同的處理。我創建了一個演示程序,僅僅是這樣的:MongoCursor在單獨的線程中回滾

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遊標可以做到這樣嗎?如果可以的話,它會很好,因爲它會使搜索條件的處理更高效,並且可以同時執行。

回答

1

除非專門設計允許它,否則您不能隨意共享線程之間更改狀態的任何對象。 pymongo cursor不是爲此設計的。

您可以做的是克隆遊標,然後爲每個線程提供自己的克隆副本。見cursor.clone

+0

謝謝,看起來不錯!你知道任何原因,copy' /'deepcopy' mods在遊標的情況下不會調用這個方法嗎?這是我應該考慮在pymongo JIRA上提交嗎? – DeaconDesperado

+0

它們不會調用它,因爲它們只查找類的__copy __()'和__deepcopy __()'方法,而我沒有看到爲'cursor'定義的方法。 – JohnnyHK