猿问

Python 3.6+:嵌套多处理管理器导致 FileNotFoundError

所以我试图在一个字典上使用多处理管理器,这是我最初的尝试:


from multiprocessing import Process, Manager


def task(stat):

    test['z'] += 1

    test['y']['Y0'] += 5



if __name__ == '__main__':

    test = Manager().dict({'x': {'X0': 10, 'X1': 20}, 'y': {'Y0': 0, 'Y1': 0}, 'z': 0})


    p = Process(target=task, args=(test,))

    p.start()

    p.join()


    print(test)

当然,当我运行它时,输出不是我所期望的,z正确更新而y不变!这是输出:


{'x': {'X0': 10, 'X1': 20}, 'y': {'Y0': 0, 'Y1': 0}, 'z': 1}

然后我用谷歌搜索,在这里找到了一个解释,显然嵌套的字典也必须是Manager().dict()s 而不是普通的 python 字典(可能从 Python 3.6 开始)。所以我做了以下事情:


from multiprocessing import Process, Manager


def task(stat):

    test['z'] += 1

    test['y']['Y0'] += 5



if __name__ == '__main__':

    test = Manager().dict({'x': Manager().dict({'X0': 10, 'X1': 20}), 'y': Manager().dict({'Y0': 0, 'Y1': 0}), 'z': 0})


    p = Process(target=task, args=(test,))

    p.start()

    p.join()


    print(test)

    print(test['y'])

但是,我得到了这个无法解释的错误,而不是它正常工作,为了清楚起见,它分为三个部分。第一部分对应于,test['y']['Y0'] += 5而第二部分是简单的print(test),最后是输出print(test['y'])

我不确定为什么会这样。内部 dicts 显然是被创建的(如输出的第二部分所示)。但是由于某种原因,它们根本无法读取或写入!为什么会这样?

额外:如果我通过 python 控制台(而不是脚本)运行相同的 python 代码,错误会FileNotFoundErrorConnectionRefusedError. 但是具有相同的确切回溯!


烙印99
浏览 179回答 1
1回答

FFIVE

随着你每次都开始一个新的经理流程,所以你真的在嵌套经理(就像标题所说的那样),这不是它应该的方式Manager()。Manager().dict()相反,您需要做的是实例化一个Manager,然后在该 manager 实例上创建字典:from multiprocessing import Process, Managerfrom multiprocessing.managers import DictProxydef task(test):&nbsp; # use parameter `test`, else you rely on forking&nbsp; &nbsp; test['z'] += 1&nbsp; &nbsp; test['y']['Y0'] += 5if __name__ == '__main__':&nbsp; &nbsp; with Manager() as m:&nbsp; &nbsp; &nbsp; &nbsp; test = m.dict({'x': m.dict({'X0': 10, 'X1': 20}),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;'y': m.dict({'Y0': 0, 'Y1': 0}),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;'z': 0})&nbsp; &nbsp; &nbsp; &nbsp; p = Process(target=task, args=(test,))&nbsp; &nbsp; &nbsp; &nbsp; p.start()&nbsp; &nbsp; &nbsp; &nbsp; p.join()&nbsp; &nbsp; &nbsp; &nbsp; print(test)&nbsp; &nbsp; &nbsp; &nbsp; print(test['y'])&nbsp; &nbsp; &nbsp; &nbsp; # convert to normal dict before closing manager for persistence&nbsp; &nbsp; &nbsp; &nbsp; # in parent or for printing dict behind proxies&nbsp; &nbsp; &nbsp; &nbsp; d = {k: dict(v) if isinstance(v, DictProxy) else v&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for k, v in test.items()}&nbsp; &nbsp; print(d) # Manager already closed here示例输出:{'x': <DictProxy object, typeid 'dict' at 0x7f98cdaaa588>, 'y': <DictProxy object, typeid 'dict' at 0x7f98cda99c50>, 'z': 1}{'Y0': 5, 'Y1': 0}{'x': {'X0': 10, 'X1': 20}, 'y': {'Y0': 5, 'Y1': 0}, 'z': 1}Process finished with exit code 0Manager.Lock如果您计划从多个进程修改管理器对象,您还需要使用它。
随时随地看视频慕课网APP

相关分类

Python
我要回答