3

我正在使用 Python“units”包(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

4

2 回答 2

2

似乎问题不在于 Unit 实例不可选择,因为您的案例显示其他情况,而不是反序列化的实例与原始实例比较不相等,因此即使它们是等价的,它们也被视为不兼容的单元。

我以前从未使用过单元,但在浏览了它的源代码之后,问题似乎是units.compatibility.compatible检查两个实例是否比较相等,但 LeafUnit 或其基础定义了一个__eq__方法,因此检查对象的身份(根据 python 的语义)。

也就是说,两个单元实例只有在它们是相同的实例(相同的内存地址等)时才会比较相等,而不是两个相等的实例。通常,在您解开序列化实例后,它将与原始实例不同(等效,是的,但不一样)

一个解决方案可能是猴子补丁units.abstract.AbstractUnit 有一个__eq__方法:

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

请注意,比较实例的表示不是最理想的,但不熟悉单位是我能想到的最好的方法。最好要求作者使单位更“比较友好”。

于 2011-01-03T08:50:00.213 回答
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)
于 2011-01-03T10:37:54.330 回答