2011-01-03 2 views
3

Я использую пакет «units» Python (http://pypi.python.org/pypi/units/), и я столкнулся с некоторыми проблемами при попытке рассолить их. Я попытался сварить его до самого простого случая, чтобы попытаться выяснить, что происходит. Вот мой простой тест:Можно ли рассолить единицы «единиц» питона?

from units import unit, named_unit 
from units.predefined import define_units 
from units.compatibility import compatible 
from units.registry import REGISTRY 

a = unit('m') 
a_p = pickle.dumps(a) 
a_up = pickle.loads(a_p) 

logging.info(repr(unit('m'))) 
logging.info(repr(a)) 
logging.info(repr(a_up)) 

logging.info(a.is_si()) 
logging.info(a_up.is_si()) 

logging.info(compatible(a,a_up)) 
logging.info(a(10) + a_up(10)) 

Выход я вижу, когда я бегу это:

LeafUnit('m', True) 
LeafUnit('m', True) 
LeafUnit('m', True) 
True 
True 
False 
IncompatibleUnitsError 

Я бы понял, если травильные агрегаты ломали их, если бы не тот факт, что Функция repr() возвращает для них одинаковые результаты. Что мне не хватает?

Это использование v0.04 пакета единиц, и Google App Engine SDK 1.4 1

ответ

2

кажется, что проблема не в том случаи, блок не pickable, так как ваш случай показывает, в противном случае, но вместо де- Сериализованный экземпляр не сравнивается с исходным экземпляром, поэтому они рассматриваются как несовместимые единицы, даже если они эквивалентны.

Я никогда не использовал блок раньше, но после того, как скользя его источник, кажется, что проблема заключается в том, что units.compatibility.compatible проверяет оба экземпляра сравнения равны, но LeafUnit, ни его основы определяют __eq__ метод, следовательно, идентичность объекта проверяется вместо (на семантику Питона).

То есть, два экземпляра единицы будут сравнивать только равные, если они являются того же экземпляра (тот же адрес памяти и т. Д.), А не два эквивалентных. Как правило, после того, как вы распакуете сериализованный экземпляр, это будет не тот же экземпляр, что и исходный (эквивалент, да, но не тот же)

Решение может быть для блоков обезьян-патчей.abstract.AbstractUnit иметь __eq__ метод:

AbstractUnit.__eq__ = lambda self, other: repr(self)==repr(other) 

Обратите внимание, что сравнение представлений экземпляров является неоптимальным, но не будучи знакомым с блоком лучшим, что я могу придумать. Лучше попросите автора (ов) сделать блок более «сопоставимым».

+0

Интересной. Ясно, что не * ideal *, но должен позволять мне разбираться, пока библиотека не будет обновлена. Я думаю, что я просто буду определять это в классе, так как я включаю его локально. Я сейчас свяжусь с автором, и я посмотрю, что они думают. – woodardj

0

Если вы хотите, что pickle создает те же экземпляры, как ваш код, то вы можете зарегистрировать __reduce__() реализации в copy_reg.dispatch_table:

import copy_reg 

from units import LeafUnit 

def leafunit_reduce(self): 
    return LeafUnit, (self.specifier, self.is_si()) 

copy_reg.pickle(LeafUnit, leafunit_reduce) 
+0

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