Как скопировать вложенный словарь?

Рейтинг: 1Ответов: 1Опубликовано: 06.04.2023

Я работаю с multiprocessing и использую manager.dict() для создания вложенного словаря, доступного разным процессам. Процессы вносят туда данные и все работает отлично, но я хочу использовать pickle\dill для выгрузки словарь, чтобы запуская программу заново мне не нужно было еще раз заполнять вложенный словарь. Но так как словарь имеет тип multiprocessing.managers.DictProxy загрузить его, после сохранения на компьютере нельзя. И я подумал перед тем как выгружать, поменять тип с multiprocessing.managers.DictProxy на dict, но метода который так делает, я не нашел. Есть ли алгоритм который бы прошелся по всему вложенному словарю и вернул копию?

Ответы

▲ 3Принят

Как обычно в таких случаях, если у класса нет специального метода для преобразования в словарь, можно просто сделать новый словарь, подав ему на вход ваш класс:

from multiprocessing import Manager

manager = Manager()
man_dct = manager.dict({'test': 123, 'fafdf': {2323: 234234, 'sdfsdf': 'sdfsdf'}})
print(type(man_dct), man_dct)
dct = dict(man_dct)
print(type(dct), dct)

Вывод:

<class 'multiprocessing.managers.DictProxy'> {'test': 123, 'fafdf': {2323: 234234, 'sdfsdf': 'sdfsdf'}}
<class 'dict'> {'test': 123, 'fafdf': {2323: 234234, 'sdfsdf': 'sdfsdf'}}

Если такие словари рекурсивно вложены, можно их рекурсивно обойти и превратить в обычные словари:

from multiprocessing import Manager
from multiprocessing.managers import DictProxy

def to_dict(item):
    if isinstance(item, DictProxy):
        return {k: to_dict(v) for k, v in item.items()}
    return item

manager = Manager()
man_dct = manager.dict({'test': 123, 'fafdf': manager.dict({2323: 234234, 'sdfsdf': 'sdfsdf'})})
print(type(man_dct), man_dct)
dct = to_dict(man_dct)
print(type(dct), dct)

Вывод:

<class 'multiprocessing.managers.DictProxy'> {'test': 123, 'fafdf': <DictProxy object, typeid 'dict' at 0x1bfa660ccd0>}
<class 'dict'> {'test': 123, 'fafdf': {2323: 234234, 'sdfsdf': 'sdfsdf'}}