Pickle: AttributeError: объект 'модуль' не имеет атрибута

Я нашел много обсуждений по этому поводу, но проблема всех из них - это пространство имен. Моя проблема не связана с пространством имен.

Небольшой пример:

import cPickle as pickle
from uncertainties import Variable

class value(Variable):
    def __init__(self, args, showing=False):
        self.show = showing
        Variable.__init__(self, args[0], args[1])

val = value((3,1), True)
print val.nominal_value, val.std_dev(), val.show
fobj = file("pickle.file", "w")
pickle.dump(val, fobj)
fobj.close()

fobj = file("pickle.file", "r")
val = pickle.load(fobj)
fobj.close()
print val.nominal_value, val.std_dev(), val.show

Вывод этого кода:

3.0 1.0 True
3.0 1.0
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/usr/lib/python2.7/dist-packages/IPython/utils/py3compat.pyc in execfile(fname, *where)
    173             else:
    174                 filename = fname
--> 175             __builtin__.execfile(filename, *where)

/home/markus/pickle.py in <module>()
     19 val = pickle.load(fobj)
     20 fobj.close()
---> 21 print val.nominal_value, val.std_dev(), val.show

AttributeError: 'value' object has no attribute 'show'

Пространство имен одинаково при травлении и распаковке. Все атрибуты uncertainties.Variable восстановлены - пропущено только мое добавленное "шоу".


person Chickenmarkus    schedule 27.02.2013    source источник
comment
Что такое модуль uncertainties? От куда это?   -  person Martijn Pieters    schedule 27.02.2013
comment
Можете ли вы придумать автономный пример этого, то есть такой, с которым мы можем поэкспериментировать?   -  person NPE    schedule 27.02.2013
comment
@NPE: мне удалось воспроизвести его, как только я обнаружил uncertainties project; он использует собственный __getstate__ метод.   -  person Martijn Pieters    schedule 27.02.2013
comment
Мне не разрешили публиковать ссылки как новому пользователю. Но я нашел этот модуль на исходной странице python.org: pypi.python.org/pypi/un sureties   -  person Chickenmarkus    schedule 27.02.2013


Ответы (1)


uncertainties.Variable() class использует _ 2_ attribute для экономии памяти. В результате, чтобы его можно было мариновать, он должен определять _ 3_ метод (см. Почему я получаю сообщение об ошибке, что мой класс определяет __slots__ при попытке мариновать объект?).

Если вам нужно добавить свои собственные дополнительные атрибуты, вам придется переопределить этот __getstate__ метод. Объявление дополнительных атрибутов в собственном __slot__ атрибуте тоже, вероятно, хорошая идея:

from uncertainties import Variable

class value(Variable):
    __slots__ = ('show',)  # only list *additional* slots

    def __init__(self, args, showing=False):
        self.show = showing
        super(value, self).__init__(args[0], args[1])

    def __getstate__(self):
        obj_slot_values = {}
        for cls in type(self).mro():
            obj_slot_values.update((k, getattr(self, k)) for k in getattr(cls, '__slots__', ()))
        # Conversion to a usual dictionary:
        return obj_slot_values

Этот новый __getstate__ необходим, потому что метод Variable.__getstate__ предполагает, что будет только один __slots__ атрибут, в то время как каждый класс в MRO может иметь один вместо него.

Это действительно ограничение библиотеки uncertainties; Я отправил запрос на перенос, который решает эту проблему и устраняет необходимость переопределения __getstate__ в подклассе.

person Martijn Pieters    schedule 27.02.2013
comment
Хорошо, простой способ, но его трудно найти с помощью этой общей ошибки AttributeError. Большое спасибо. - person Chickenmarkus; 27.02.2013
comment
@Chickenmarkus: Благодаря Martijn, который прислал мне патч, последняя версия неопределенностей на Github позволяет напрямую выбирать ваш value класс без необходимости определять свой собственный __getstate__(). - person Eric O Lebigot; 28.02.2013
comment
@Chickenmarkus: я только что загрузил версию 1.9.1 своего пакета неопределенностей (pypi.python.org/pypi/ неопределенности): теперь ваш подкласс должен быть напрямую рассортирован (нет необходимости определять свой собственный __getstate__. - person Eric O Lebigot; 01.03.2013
comment
@EOL: Да, с версией 1.9.1 мой первый пример тоже работает. Спасибо. - person Chickenmarkus; 04.03.2013