是否有可能腌制Python“单位”?单位?

发布于 2024-10-10 12:38:48 字数 811 浏览 4 评论 0原文

我正在使用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() 为它们返回相同的结果,我会理解酸洗单元是否会破坏它们。我缺少什么?

这是使用units包的v0.04和Google App Engine 1.4 SDK 1

I'm using the Python "units" package (http://pypi.python.org/pypi/units/) and I've run into some trouble when trying to pickle them. I've tried to boil it down to the simplest possible to case to try and figure out what's going on. Here's my simple test:

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))

The output I'm seeing when I run this is:

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

I'd understand if pickling units broke them, if it weren't for the fact that repr() is returning identical results for them. What am I missing?

This is using v0.04 of the units package, and Google App Engine 1.4 SDK 1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岁吢 2024-10-17 12:38:48

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

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

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

解决方案可能是对units.abstract.AbstractUnit进行猴子补丁以使其具有 __eq__< /code> 方法:

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

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

It seems that the problem is not that Unit instances are not pickable since your case shows otherwise but rather than the de-serialized instance does not compare equal to the original instance hence they're treated as incompatible units even though they're equivlent.

I have never used unit before but after skimming its source it seems that the problem is that units.compatibility.compatible checks if both instances compare equal but LeafUnit nor its bases define an __eq__ method hence object's identity is checked instead (per python's semantics).

That is, two unit instances will only compare equal if they are the same instance (the same memory address, etc), not two equivalent ones. Normally, after you unpickle a serialized instance it will not be the same instance as the original one (equivalent, yes, but not the same)

A solution could be to monkey-patch units.abstract.AbstractUnit to have an __eq__ method:

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

Note that comparing the instances' representations is suboptimal but not being familiar with unit is the best I can come up with. Better ask the author(s) to make unit more "comparable friendly".

み青杉依旧 2024-10-17 12:38:48

如果您希望 pickle 创建与您的代码相同的实例,那么您可以在 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)

If you'd like that pickle creates the same instances as your code then you could register __reduce__() implementation in 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文