【发布时间】:2023-02-24 01:44:13
【问题描述】:
我正在尝试使用由多个进程共享的缓存,使用multiprocessing.Manager's dict。下面的演示给出了一些上下文(来自this answer):
import multiprocessing as mp
import time
def foo_pool(x, cache):
if x not in cache:
time.sleep(2)
cache[x] = x*x
else:
print('using cache for', x)
return cache[x]
result_list = []
def log_result(result):
result_list.append(result)
def apply_async_with_callback():
manager = mp.Manager()
cache = manager.dict()
pool = mp.Pool()
jobs = list(range(10)) + list(range(10))
for i in jobs:
pool.apply_async(foo_pool, args = (i, cache), callback = log_result)
pool.close()
pool.join()
print(result_list)
if __name__ == '__main__':
apply_async_with_callback()
运行上面的代码会得到如下结果:
using cache for 0
using cache for 2
using cache for 4
using cache for 1
using cache for 3
using cache for 5
using cache for 7
using cache for 6
[25, 16, 4, 1, 9, 0, 36, 49, 0, 4, 16, 1, 9, 25, 49, 36, 64, 81, 81, 64]
所以缓存按预期工作。
我想要实现的是给这个manager.dict() 一个大小限制,就像functools.lru_cache 的maxsize 参数一样。我目前的尝试是:
class LimitedSizeDict:
def __init__(self, max_size):
self.max_size = max_size
self.manager = mp.Manager()
self.dict = self.manager.dict()
self.keys = self.manager.list()
def __getitem__(self, key):
return self.dict[key]
def __setitem__(self, key, value):
if len(self.keys) >= self.max_size:
oldest_key = self.keys.pop(0)
del self.dict[oldest_key]
self.keys.append(key)
self.dict[key] = value
def __contains__(self, key):
return key in self.dict
def __len__(self):
return len(self.dict)
def __iter__(self):
for key in self.keys:
yield key
然后使用以下命令启动进程:
def apply_async_with_callback():
cache = LimitedSizeDict(3)
pool = mp.Pool()
jobs = list(range(10)) + list(range(10))
for i in jobs:
pool.apply_async(foo_pool, args = (i, cache), callback = log_result)
pool.close()
pool.join()
print(result_list)
但这给了我一个空列表:[]。
我想我可能必须继承 multiprocessing.managers.DictProxy 类才能实现这一点,所以我查看了源代码。但是好像没有DictProxy的类定义。
如何给这个共享字典缓存一个大小限制?提前致谢。
【问题讨论】:
标签: python caching multiprocessing