Можно ли засолить «юниты» юнитов питона? - PullRequest
3 голосов
/ 03 января 2011

Я использую пакет Python "unit" (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 1.4 SDK 1

Ответы [ 2 ]

2 голосов
/ 03 января 2011

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

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

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

Решением может быть использование monkey-patch unit.abstract.AbstractUnit для использования метода __eq__:

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

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

0 голосов
/ 03 января 2011

Если вы хотите, чтобы 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)
...