[英]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.