Python进程池修改Manager共享变量时出现KeyError问题求助
问题原因
你遇到的KeyError是因为**multiprocessing.Manager()创建的字典是代理对象**:当执行sharedDict[k] = {}时,你把一个普通本地字典赋值给了共享字典的键,这个本地字典并非共享代理对象。后续修改sharedDict[k]['current'] = v时,操作的是当前进程内的本地字典副本,并没有同步到Manager维护的共享字典中。当执行print语句读取sharedDict[k]['current']时,实际读取的是Manager共享字典里的空字典(之前的赋值未同步),因此抛出KeyError。
修复方案
有两种可行的修复方式:
方式1:使用Manager创建嵌套共享字典
将嵌套的普通字典替换为Manager提供的共享字典,确保所有层级的字典都是代理对象,修改操作能同步到共享空间:
from multiprocessing import Pool, Manager def task(args): k, v, sharedDict, lock, manager = args # 新增manager参数 with lock: if k not in sharedDict: # 用manager.dict()创建嵌套的共享字典 sharedDict[k] = manager.dict() sharedDict[k]['current'] = v print(f"sharedDict[k]['current'] = {sharedDict[k]['current']}") def main(): manager = Manager() lock = manager.Lock() dic = manager.dict() pool = Pool(processes=2) # 把manager传入任务参数 tasks = [('a', {'A': 1}, dic, lock, manager), ('b', {'B': 2}, dic, lock, manager), ('c', {'C': 3}, dic, lock, manager), ('d', {'D': 4}, dic, lock, manager)] pool.map(task, tasks) pool.close() pool.join() if __name__ == '__main__': main()
方式2:一次性赋值完整字典
直接把包含current键的完整字典赋值给共享字典的键,避免修改嵌套的本地字典:
from multiprocessing import Pool, Manager def task(args): k, v, sharedDict, lock = args with lock: if k not in sharedDict: # 直接赋值完整的字典,让代理对象同步整个结构 sharedDict[k] = {'current': v} print(f"sharedDict[k]['current'] = {sharedDict[k]['current']}") def main(): manager = Manager() lock = manager.Lock() dic = manager.dict() pool = Pool(processes=2) tasks = [('a', {'A': 1}, dic, lock), ('b', {'B': 2}, dic, lock), ('c', {'C': 3}, dic, lock), ('d', {'D': 4}, dic, lock)] pool.map(task, tasks) pool.close() pool.join() if __name__ == '__main__': main()
关键说明
Manager.dict()返回的是代理对象,仅对直接的键值赋值做同步,嵌套的普通字典无法被自动代理。- 两种方案的核心都是确保修改操作能被Manager的代理对象捕获并同步:要么用嵌套的共享字典,要么一次性完成完整字典的赋值。
内容的提问来源于stack exchange,提问作者zhangshuai
相关产品推荐
相关产品推荐

