Python多进程锁问题
我想用Python的多进程模块把一组字典合并在一起。
下面是我代码的简化版本:
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import multiprocessing
import functools
import time
def merge(lock, d1, d2):
time.sleep(5) # some time consuming stuffs
with lock:
for key in d2.keys():
if d1.has_key(key):
d1[key] += d2[key]
else:
d1[key] = d2[key]
l = [{ x % 10 : x } for x in range(10000)]
lock = multiprocessing.Lock()
d = multiprocessing.Manager().dict()
partial_merge = functools.partial(merge, d1 = d, lock = lock)
pool_size = multiprocessing.cpu_count()
pool = multiprocessing.Pool(processes = pool_size)
pool.map(partial_merge, l)
pool.close()
pool.join()
print d
运行这个脚本时我遇到了这个错误。我该怎么解决呢?
RuntimeError: Lock objects should only be shared between processes through inheritance
在这个条件下,
merge
函数里的lock
是必要的吗?还是说Python会自动处理这个问题?我觉得
map
应该是把一个列表的内容映射到另一个列表,而不是把所有东西都放到一个对象里。那么有没有更优雅的方法来做这些事情呢?
1 个回答
12
下面的代码可以在不同的操作系统上运行,包括Windows,并且适用于Python 2和Python 3。它使用了一个进程池的初始化器,目的是在每个子进程中将管理字典设置为全局变量。
顺便提一下:
- 使用锁对于管理字典来说是没必要的。
- 进程池中的进程数量默认是根据你的CPU数量来决定的。
- 如果你对结果不感兴趣,可以用
apply_async
来代替map
。
import multiprocessing
import time
def merge(d2):
time.sleep(1) # some time consuming stuffs
for key in d2.keys():
if key in d1:
d1[key] += d2[key]
else:
d1[key] = d2[key]
def init(d):
global d1
d1 = d
if __name__ == '__main__':
d1 = multiprocessing.Manager().dict()
pool = multiprocessing.Pool(initializer=init, initargs=(d1, ))
l = [{ x % 5 : x } for x in range(10)]
for item in l:
pool.apply_async(merge, (item,))
pool.close()
pool.join()
print(l)
print(d1)