Почему я не могу солить этот объект?
У меня есть класс (ниже):
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
В вашем коде есть несколько второстепенных "побочных" проблем: внезапное появление "транспорта" в имени класса, используемого в тесте (это не имя класса, которое вы определяете), сомнительное попирание встроенного идентификатора 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__
.
Ответ 2
Он не работает, потому что он не может найти __getstate__()
для вашего объекта. Рассол нуждается в них, чтобы определить, как рассолковать/расклеить объект. Вам просто нужны методы __getstate__()
и __setstate__()
.
См. пример TextReader в документах: http://docs.python.org/library/pickle.html
Обновление. Я просто просмотрел страницу sourceforge для модуля Mock, и я думаю, что вы также используете это неправильно.
Вы издеваетесь над файловым объектом, но когда pickle пытается его прочитать, он ничего не получит, поэтому getattr()
не возвращает ничего.
Ответ 3
file = open('testpickle.dat', 'w')
file = Mock()
Вы теряете здесь ссылку на открытый файл. Возможно, это проблема?