Как разблокировать объект, класс которого существует в другом пространстве имен (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: io.UsupportedOperation: read
  • травление и расчистка пользовательского класса
  • Как загрузить объект рассола и разрешить определенные ссылки
  • как сохранить словарь в рассоле
  • cPickle.UnpicklingError: недопустимый ключ загрузки
  • Как распиливать и распаковывать экземпляры класса, который наследуется от defaultdict?
  • cPickle - игнорировать материал, который он не может сериализовать, вместо того, чтобы создавать исключение
  • Загружать данные из файла рассола Python в цикле?
  • Python - лучший язык программирования в мире.