2010-01-12 3 views
14

У меня есть класс (ниже):Почему я не могу солить этот объект?

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 

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

Любые идеи?

Бен

+1

В качестве примечания стороны: «ключ в self.kwargs.iterkeys()» генерирует список ключей и выполняет поиск через них. Лучше использовать ключ в self.kwargs, который пытается выполнить поиск в хэш-таблице (быстрее). – ebo

+1

Когда вы просите о помощи в отладке, это помогает предоставить достаточно кода для воспроизведения проблемы. Это помогает еще больше удалить все, что не имеет отношения к коду, который вы публикуете. –

ответ

29

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

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

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

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

+0

Спасибо за подтверждение - 100+ просмотров, и вы первый, кто согласился со мной ...Я беспокоился –

+4

@coonj, я думаю, людям нелегко видеть, почему нужно определять методы обработки состояния, так как обычно они не нужны (и нигде не ясно, что '__getattr__' делает их необходимыми). –

+0

Thanks Alex & coonj, Этот тест должен был воссоздать проблему, с которой я столкнулся, отправив удаленный объект по витой сессии pb. Это все немного ветчины - я действительно ценю ваши очки. Мое обучение на python просто зацепило несколько кликов. Еще раз спасибо за помощь. Ben –

2
file = open('testpickle.dat', 'w') 
    file = Mock() 

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

+0

Это, по-видимому, вероятная причина проблемы. – jathanism

6

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

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

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

Смежные вопросы