2014-08-28 180 views
25

我正在嘗試使用部分函數,​​以便pool.map()可以針對具有多個參數(在本例中爲Lock()對象)的函數。Python共享進程之間的鎖

下面是示例代碼(從答案帶到我的前面的問題):

from functools import partial 

def target(lock, iterable_item): 
    for item in items: 
     # Do cool stuff 
     if (... some condition here ...): 
      lock.acquire() 
      # Write to stdout or logfile, etc. 
      lock.release() 

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    pool = multiprocessing.Pool() 
    l = multiprocessing.Lock() 
    func = partial(target, l) 
    pool.map(func, iterable) 
    pool.close() 
    pool.join() 

然而,當我運行此代碼,我得到的錯誤:

Runtime Error: Lock objects should only be shared between processes through inheritance. 

我是什麼在這裏失蹤?我怎樣才能分享我的子流程之間的鎖?

+0

還有關於同樣的問題的另一個問題,雖然他們的具體錯誤是不同的 - [使用多處理.Pool:酸洗錯誤鎖定問題](http://stackoverflow.com/questions/17960296/trouble-usinga-a-鎖 - 多處理 - 池 - 酸洗 - 錯誤) – 2014-08-28 21:03:32

回答

46

對不起,我應該在回答您的其他問題時發現了這個問題。您無法將正常的multiprocessing.Lock對象傳遞給Pool方法,因爲它們不能被酸洗。有兩種方法可以解決這個問題。一種方法是建立Manager()並傳遞Manager.Lock()

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    pool = multiprocessing.Pool() 
    m = multiprocessing.Manager() 
    l = m.Lock() 
    func = partial(target, l) 
    pool.map(func, iterable) 
    pool.close() 
    pool.join() 

這是一個有點重量級的,雖然,使用Manager需要產生另一個進程來承載Manager服務器。並且所有對acquire/release的呼叫都必須通過IPC發送到該服務器。

另一種選擇是在池創建時使用initializer kwarg傳遞常規multiprocessing.Lock()。這會讓你的鎖實例中的所有童工全球:

def target(iterable_item): 
    for item in items: 
     # Do cool stuff 
     if (... some condition here ...): 
      lock.acquire() 
      # Write to stdout or logfile, etc. 
      lock.release() 
def init(l): 
    global lock 
    lock = l 

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    l = multiprocessing.Lock() 
    pool = multiprocessing.Pool(initializer=init, initargs=(l,)) 
    pool.map(target, iterable) 
    pool.close() 
    pool.join() 

第二個解決方案具有不再需要partial副作用。

+0

好的,再次感謝你,先生。這看起來正是我所需要的。真的很感激繼續的幫助!其他選項看起來超級參與。我將使用初始化函數來共享全局鎖。 – DJMcCarthy12 2014-08-28 21:47:47

+0

這工作得很好。我還在init中加入了一個'Queue',以保存在每次調用中傳遞的信息。 – fantabolous 2015-08-17 15:11:43

+1

@dano非常感謝您的回答,我也有相同的查詢,並且這個查詢完美地解決了這個問題,但是我有另一個查詢,爲什麼這種方法不經常用於在進程間共享狀態,而不是通過Manager對象運行服務器進程和代理訪問有其自己的開銷? – bawejakunal 2016-02-22 17:00:47