簡體   English   中英

Python 在進程之間共享鎖

[英]Python sharing a lock between processes

我正在嘗試使用部分函數,​​以便 pool.map() 可以針對具有多個參數的函數(在本例中為 Lock() 對象)。

這是示例代碼(取自我上一個問題的答案):

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.

我在這里缺少什么? 如何在我的子進程之間共享鎖?

您不能將普通的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

這是一個版本(使用Barrier而不是Lock ,但你明白了)它也可以在 Windows 上運行(丟失的fork會導致額外的麻煩):

import multiprocessing as mp

def procs(uid_barrier):
    uid, barrier = uid_barrier
    print(uid, 'waiting')
    barrier.wait()
    print(uid, 'past barrier')    

def main():
    N_PROCS = 10
    with mp.Manager() as man:
        barrier = man.Barrier(N_PROCS)
        with mp.Pool(N_PROCS) as p:
            p.map(procs, ((uid, barrier) for uid in range(N_PROCS)))

if __name__ == '__main__':
    mp.freeze_support()
    main()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM