Как разблокировать объект, класс которого существует в другом пространстве имен (python)?

Если у меня есть скрипт, который определяет класс:

script = """ class myClass: def __init__(self): self.name = 'apple' self.color = 'green' """ 

а затем выполните этот скрипт в своем собственном пространстве имен dict:

 NS = {} exec script in NS 

а затем создать экземпляр класса и рассортировать его:

 a = NS['myClass']() import pickle save = pickle.dumps(a) 

Теперь, если я попытаюсь раскрыть ее:

 load = pickle.loads(save) 

Я получаю ошибку

 AttributeError: 'module' object has no attribute 'myClass' 

Я понимаю, что это не работает, потому что python не знает, где найти myClass, чтобы перестроить объект. Но myClass существует в NS dict. Есть ли способ сказать pickle, где найти класс для объекта, который он загружает?

2 Solutions collect form web for “Как разблокировать объект, класс которого существует в другом пространстве имен (python)?”

Я обнаружил решение этого. Кажется, что проблема заключается в выполнении кода в dict запрещает python определять, где определяется класс. Решение состоит в том, чтобы создать пустой модуль, выполнить код в модуле, а затем добавить модуль в sys.modules, чтобы python знал об этом.

 script = """ class myClass: def __init__(self): self.name = 'apple' self.color = 'green' """ import imp, sys moduleName = 'custom' module = imp.new_module(moduleName) exec script in module.__dict__ sys.modules[moduleName] = module 

Теперь можно рассортировать и распечатывать экземпляр класса:

 import pickle a = module.myClass() s = pickle.dumps(a) b = pickle.loads(s) 

Вы можете пойти на один шаг дальше и восстановить объект в том виде, который вам нужен.

 import pickle import copy_reg class myClass(object): def __init__(self): self.apple = 'banana' class otherclass(object): def __init__(self): self.apple = 'existential woe' def pickle_an_object(o): print "pickling %s" % str(o) return otherclass, (o.apple,) copy_reg.pickle(myClass, pickle_an_object) foo = myClass() s = pickle.dumps(foo) del myClass del otherclass class otherclass(object): def __init__(self, appletype): self.apple = 'not %s' % appletype o2 = pickle.loads(s) print o2.apple 

Основная идея заключается в том, что вы кладете свой класс в «троянскую лошадь», где его реконструкция создает экземпляр другого класса из того, что он изначально был.

Не имеет значения, что otherclass на травильной стороне. Все, что имеет значение, заключается в том, что он существует на том же пути модуля, что и класс «destination» – pickle просто помещает строковое представление имени модуля в сериализованный поток.

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

  • Мы регистрируем пользовательский pickler для myClass . Это можно сделать с помощью функции copy_reg или __reduce_ex__ .
  • Наш заказчик говорит, что «расчешите это как экземпляр otherclass » (который является манекеном. Вам не нужно «настоящее» содержимое otherclass на травильной стороне, потому что все, что входит в рассол, – это имя модуля / класса).
  • Мы сортируем объект и «отправляем его по проводам», где существует реальная версия otherclass .
  • С другой стороны, otherclass с данными из кортежа, возвращаемого пользовательской функцией травления.

Python может быть довольно мощным!

  • Я продолжаю получать «недопустимый символ в идентификаторе» при открытии файла в python
  • Почему pickle __getstate__ принимает в качестве возвращаемого значения тот самый экземпляр, который требуется __getstate__ для рассола в первую очередь?
  • Чтение из файла с использованием pickle и для цикла в python
  • Python: невозможно определить ошибки объектов модуля
  • Соленые огурцы: Почему они так называли?
  • Травление питона после изменения каталога модуля
  • Python ValueError: небезопасный струйный рассол
  • Как рассолить себя?
  • Что это означает, что объект может быть сорван (или маринован)?
  • травление и расчистка пользовательского класса
  • _pickle в python3 не работает для большой экономии данных
  • Python - лучший язык программирования в мире.