Python在进程之间共享锁
- 2025-02-11 09:50:00
- admin 原创
- 47
问题描述:
我正在尝试使用部分函数,以便 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.
我在这里错过了什么?如何在子进程之间共享锁?
解决方案 1:
您无法将普通multiprocessing.Lock
对象传递给Pool
方法,因为它们无法被 pickle。有两种方法可以解决这个问题。一种是创建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
的所有调用都必须通过 IPC 发送到该服务器。acquire
`release`
multiprocessing.Lock()
另一个选项是在创建 Pool 时使用kwarg传递常规值initializer
。这将使您的锁实例在所有子 Worker 中成为全局的:
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
。
解决方案 2:
这是一个版本(使用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()
相关推荐
热门文章
项目管理软件有哪些?
热门标签
云禅道AD