Как мне настроить словарь, содержащий модуль и класс?

#python #python-3.x #pickle

#python #python-3.x #настройка

Вопрос:

Мне нужно назначить модуль и класс ключу словаря. Затем настройте этот словарь в файл. Затем позже загрузите файл pkl, затем импортируйте и создайте экземпляр класса на основе этого значения ключа словаря.

Я пробовал это:

 import module_example
from module_example import ClassExample

dictionary = {'module': module_example, 'class': ClassExample)
  

Тем не менее, он не сохранит ссылку на module_exmaple.py в файле pkl.

Я попробовал обходной путь использования строки вместо имени модуля и класса. Но это приведет к беспорядку, если имя модуля будет переработано или местоположение будет изменено в будущем.

Есть ли в любом случае возможность сделать это напрямую? Каким-то образом сохраните ссылку на модуль и класс в словаре, а затем импортируйте и создайте экземпляр на основе этой ссылки?

Ответ №1:

Это работает для одного класса. Если вы хотите сделать это в нескольких модулях и классах, вы можете расширить следующий код.

module_class_writer.py

 import module_example
from module_example import ClassExample

included_module = ["module_example"]
d = {}
for name, val in globals().items():
    if name in included_module:
        if "__module__" in dir(val):
            d["module"] = val.__module__
            d["class"] = name

#d = {'module': module_example, 'class': ClassExample}

import pickle
filehandler = open("imports.pkl","wb")
pickle.dump(d, filehandler)
filehandler.close()
  

module_class_reader.py

 import pickle
filehandler = open("imports.pkl",'rb')
d = pickle.load(filehandler)
filehandler.close()

def reload_class(module_name, class_name):
    mod = __import__(module_name, fromlist=[class_name])
    reload(mod)
    return getattr(mod, class_name)

if "class" in d and "module" in d: 
    reload(__import__(d["module"]))
    ClassExample = reload_class(d["module"], d["class"])
  

Ответ №2:

Если вы хотите, чтобы необработанный класс был точно таким же объектом, который был изменен, вам придется сохранить код класса (используя внешнюю библиотеку, такую, например, как dill).

В противном случае, в стандартном pickle невозможно сохранить ссылку на класс, который «переживет» рефакторинг.

Комментарии:

1. Мне не нужен один и тот же объект. Но мне нужна ссылка на класс. Чтобы я мог создать экземпляр нового объекта на основе этой ссылки. Если имя этого класса и / или местоположение будет переработано, я бы хотел, чтобы ссылка также отражала это. Каким-либо образом это можно сделать?

2. @Emily: Python никак не сможет определить, что новый класс и старый класс являются «одним и тем же классом» после такого рефакторинга.