Почему я не могу засолить этот объект? - PullRequest
14 голосов
/ 12 января 2010

У меня есть класс (ниже):

class InstrumentChange(object):
    '''This class acts as the DTO object to send instrument change information from the
       client to the server. See InstrumentChangeTransport below
    '''
    def __init__(self, **kwargs):
        self.kwargs = kwargs
        self._changed = None

    def _method_name(self, text):
        return text.replace(' ','_').lower()

    def _what_changed(self):
        ''' Denotes the column that changed on the instrument returning the column_name of what changed.'''
        if not self._changed:
            self._changed = self._method_name(self.kwargs.pop('What Changed'))

        return self._changed

    def __getattr__(self, attr):
        for key in self.kwargs.iterkeys():
            if self._method_name(key) == attr:
                return self.kwargs[key]

    def __str__(self):
        return "Instrument:%s" % self.kwargs

    __repr__ = __str__

    what_changed = property(_what_changed)

Когда я запускаю следующий тест:

def test_that_instrumentchangetransport_is_picklable(self):
        test_dict = {'Updated': 'PAllum', 'Description': 'BR/EUR/BRAZIL/11%/26/06/2017/BD',
        'Ask Q': 500, 'Bbg': 'On', 'C Bid': 72.0, 'Benchmark': 'NL/USD/KKB/7.000%/03/11/2009/BD',
        'ISIN': 'XS0077157575', 'Bid YTM': 0.0, 'Bid Q': 100, 'C Ask': 72.25, 'Ask YTM': 0.0, 'Bid ASW': 0.0,
        'Position': 1280000, 'What Changed': 'C Bid', 'Ask ASW': 0.0}
        ins_change = InstrumentChangeTransport(**test_dict)
        assert isinstance(ins_change, InstrumentChangeTransport)

        # Create a mock filesystem object
        file = open('testpickle.dat', 'w')
        file = Mock()
        pickle.dump(ins_change, file)

Я получаю:

Traceback (most recent call last):
  File "c:\python23\lib\site-packages\nose-0.11.0-py2.3.egg\nose\case.py", line 183, in runTest
    self.test(*self.arg)
  File "C:\Code\branches\demo\tests\test_framework.py", line 142, in test_that_instrumentchangetransport_is_picklable
    pickle.dump(ins_change, file)
  File "C:\Python23\Lib\copy_reg.py", line 83, in _reduce_ex
    dict = getstate()
TypeError: 'NoneType' object is not callable

Я посмотрел документы на рассол, но не совсем понял.

Есть идеи?

Ben

Ответы [ 3 ]

33 голосов
/ 12 января 2010

В вашем коде есть несколько незначительных «побочных» проблем: внезапное появление «Transport» в имени класса, используемом в тесте (это не имя класса, которое вы определяете), сомнительное попирание над встроенным идентификатором file как локальная переменная (не делайте этого - это не повредит, но привычка топтать встроенные идентификаторы однажды вызовет таинственные ошибки), злоупотребления Mock, которые уже были отметил, что по умолчанию используется самый медленный, самый грубый протокол и текст для засолки, а не двоичный файл для файла засолки.

Однако, как говорит @coonj, в основе лежит отсутствие контроля со стороны государства. «Нормальному» классу это не нужно (потому что self.__dict__ выбирается и выбирается по умолчанию в классах, в которых отсутствует контроль состояния и нет других особенностей) - но поскольку вы переопределяете __getattr__, это не относится к вашему классу , Вам просто нужно еще два очень простых метода:

def __getstate__(self): return self.__dict__
def __setstate__(self, d): self.__dict__.update(d)

, который в основном говорит pickle обращаться с вашим классом так же, как с обычным, принимая self.__dict__ как представление всего состояния экземпляра, несмотря на существование __getattr__.

7 голосов
/ 12 января 2010

Сбой, потому что не может найти __getstate__() для вашего объекта. Pickle нуждается в них, чтобы определить, как засолить / расколоть объект. Вам просто нужны методы __getstate__() и __setstate__().

См. Пример TextReader в документах: http://docs.python.org/library/pickle.html

Обновление : Я только что посмотрел на страницу sourceforge для модуля Mock, и думаю, что вы также используете его неправильно. Вы издеваетесь над файлом-объектом, но когда pickle пытается прочитать с него, он ничего не получит, поэтому getattr() ничего не возвращает.

2 голосов
/ 12 января 2010
    file = open('testpickle.dat', 'w')
    file = Mock()

Вы теряете здесь ссылку на открытый файл. Может ли это быть проблемой?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...