0

我有一個很大的代碼庫來平行。我可以避免使用單個全局隊列來重寫數百個函數的方法簽名。我知道這很混亂;請不要告訴我,如果我使用全局變量,我在這種情況下做錯了事情,它確實是最簡單的選擇。下面的代碼工作,但我不明白爲什麼。我聲明瞭一個全局multiprocessing.Queue(),但不要聲明它應該在進程之間共享(通過將它作爲參數傳遞給worker)。 python會自動將這個隊列放入共享內存嗎?在更大規模上做這件事是否安全?在python中使用多處理時可以安全地使用全局隊列嗎?

注意:您可以看到隊列在進程之間共享:工作進程開始在空隊列上工作,並在主隊列將某些工作推入隊列之前閒置一秒。

import multiprocessing 
import time 

outqueue = None 


class WorkerProcess(multiprocessing.Process): 
    def __init__(self): 
     multiprocessing.Process.__init__(self) 
     self.exit = multiprocessing.Event() 

    def doWork(self): 
     global outqueue 
     ob = outqueue.get() 
     ob = ob + "!" 
     print ob 
     time.sleep(1) #simulate more hard work 
     outqueue.put(ob) 

    def run(self): 
     while not self.exit.is_set(): 
      self.doWork() 

    def shutdown(self): 
     self.exit.set() 

if __name__ == '__main__': 
    global outqueue 
    outqueue = multiprocessing.Queue() 

    procs = [] 
    for x in range(10): 
     procs.append(WorkerProcess()) 
     procs[x].start() 

    time.sleep(1) 
    for x in range(20): 
     outqueue.put(str(x)) 

    time.sleep(10) 
    for p in procs: 
     p.shutdown() 

    for p in procs: 
     p.join() 

    try: 
     while True: 
      x = outqueue.get(False) 
      print x 
    except: 
     print "done" 
+0

我強烈要求閱讀[這個問題](http://stackoverflow.com/questions/11442892/python-multiprocessing-queue-failure)的答案,而不是下面接受的答案,我認爲這是完全錯誤的。 –

回答

1

假設你使用的是Linux,答案就是OS創建一個新進程的方式。

當一個進程在Linux中產生一個新進程時,它實際上會分配一個父進程。結果是一個包含父級屬性所有屬性的子進程。基本上是一個克隆。

在你的例子中,你正在實例化Queue,然後創建新的進程。因此,子進程將擁有相同隊列的副本,並且可以使用它。

要查看破壞的事情,只需嘗試先創建進程並創建Queue對象。您會看到具有全局變量的子項仍設置爲None,而父項將具有Queue。

在Linux上共享Queue作爲全局變量是安全的,但不推薦。在Windows上,由於不同的流程創建方法,通過全局變量共享隊列將不起作用。

programming guidelines

提及明確地傳遞資源子使用fork開始方法處理

在Unix,子進程可以利用使用在父進程創建的共享資源的全球資源。但是,最好將該對象作爲參數傳遞給子進程的構造函數。

除了使代碼(可能)與Windows和其他啓動方法兼容外,這還確保只要子進程仍然存在,對象將不會在父進程中被垃圾收集。如果在父進程中垃圾收集對象時某些資源被釋放,這可能很重要。

有關Linux分叉的更多信息,您可以閱讀它的man page

+0

我很抱歉downvote,但我認爲這是不正確的。從個人的經驗來看,這可能會導致一個過程無法通過不同的過程將'get'消息'放入隊列中的情況。我建議看看[這個問題]的答案(http://stackoverflow.com/questions/11442892/python-multiprocessing-queue-failure)。 –

+0

「將隊列作爲全局變量共享是安全的,但不推薦。」:它似乎不適用於Windows。看到我的問題:http:// stackoverflow。com/questions/42734348/sharing-synchronization-objects-through-global-namespace-vs-as-a-function-argume – max

+0

@max:正如答案中所說,我專注於Linux。我根據你的評論更新了答案。 – noxdafox

相關問題