Определение класса солений в модуле с укропом

1

Мой модуль содержит класс, который должен быть разборчивым, как экземпляр, так и определение. Я имею следующую структуру:

MyModule
|-Submodule
  |-MyClass

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

import dill as pickle

class MyClass(object):
    ...

instance = MyClass(...)
with open(..., 'wb') as file:
   pickle.dump(instance, file)

Однако при импорте этого класса он не работает:

Травление:

from MyModule.Submodule import MyClass
import dill as pickle

instance = MyClass(...)
with open(.., 'wb') as file:
    pickle.dump(instance, file)

Загрузка:

import dill as pickle

with open(..., 'rb') as file:
    instance = pickle.load(file)

>>> ModuleNotFoundError: No module named 'MyModule'

Я думаю, что определение класса сохраняется по ссылке, хотя оно не должно иметь значения по умолчанию в укропе. Это сделано правильно, когда MyClass известен как __main__.MyClass, который происходит, когда класс определен в основном скрипте.

Мне интересно, есть ли способ отделить MyClass от MyModule? Любой способ заставить его действовать как импорт верхнего уровня (__main__.MyClass), поэтому укроп знает, как загрузить его на другой машине?

Соответствующий вопрос: почему укроп сбрасывает внешние классы по ссылке независимо от того, что

Теги:
python-3.x
serialization
pickle
dill

2 ответа

0

Мне удалось сохранить экземпляр и определение моего класса, используя следующий грязный хак:

class MyClass(object):
    def save(path):
        import __main__

        with open(__file__) as f:
            code = compile(f.read(), "somefile.py", 'exec')
            globals = __main__.__dict__
            locals = {'instance': self, 'savepath': path}
            exec(code, globals, locals)

if __name__ == '__main__':
    # Script is loaded in top level, MyClass is now available under the qualname '__main__.MyClass'
    import dill as pickle

    # copy the attributes of the 'MyModule.Submodule.MyClass' instance to a bew 'MyClass' instance.
    new_instance = MyClass.__new__(MyClass)
    new_instance.__dict__ = locals()['instance'].__dict__

    with open(locals()['savepath'], 'wb') as f:       
        pickle.dump(new_instance, f)

Используя оператор exec файл может быть выполнен из __main__, поэтому определение класса также будет сохранено. Этот сценарий не должен выполняться как основной скрипт без использования функции сохранения.

  • 1
    ..... гадость ......
0

Я автор dill. Это дубликат вопроса, на который вы ссылаетесь выше. Соответствующий запрос функции GitHub: https://github.com/uqfoundation/dill/issues/128.

Я думаю, что большая проблема заключается в том, что вы хотите рассортировать объект, определенный в другом файле, который не установлен. По-моему, в настоящее время это невозможно.

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

  • 0
    Потенциально я дополню этот ответ контрольным примером, если я построю такой, который смог бы продемонстрировать мою гипотезу.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню