我正在使用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 1.4 SDK 1
答案 0 :(得分:2)
似乎问题不是单元实例不可拾取,因为你的情况显示不是这样,而是反序列化的实例与原始实例不相等,因此它们被视为不兼容的单元,即使它们是equivlent。
我以前从未使用过单位,但在略读其来源后,似乎问题是units.compatibility.compatible
检查两个实例是否相等,但LeafUnit及其基数定义了__eq__
方法,因此检查了对象的身份相反(根据python的语义)。
也就是说,如果两个单元实例 相同的实例(相同的内存地址等),而不是两个等效实例,则它们只会相等。通常,在取消对序列化实例的取消后,它将不是与原始实例相同的实例(等效,是,但不相同)
一个解决方案可能是修补单元.abstract.AbstractUnit有一个__eq__
方法:
AbstractUnit.__eq__ = lambda self, other: repr(self)==repr(other)
请注意,比较实例的表示是不是最理想的,但不熟悉单位是我能想到的最好的。更好地要求作者使单位更“友好”。
答案 1 :(得分:0)
如果您希望pickle
创建与您的代码相同的实例,那么您可以在copy_reg.dispatch_table
中注册__reduce__()
实施:
import copy_reg
from units import LeafUnit
def leafunit_reduce(self):
return LeafUnit, (self.specifier, self.is_si())
copy_reg.pickle(LeafUnit, leafunit_reduce)