Определение класса солений в модуле с укропом - PullRequest
0 голосов
/ 19 сентября 2018

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

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), чтобы укроп знал, как загрузить его на другую мою машину?

Актуальный вопрос: Почему укроп выбрасывает внешние классы по ссылке независимо от того, что

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

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

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__, поэтому определение классабудут также сохранены.Этот сценарий не должен выполняться как основной сценарий без использования функции сохранения.

0 голосов
/ 19 сентября 2018

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

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

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

...