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()が同じ結果を返しているという事実がなければ、ピクルスユニットがそれらを壊したかどうかは理解できます。私は何が欠けていますか?

これは、unitsパッケージのv0.04とGoogle App Engine 1.4SDK1を使用しています。

4

2 に答える 2

2

問題は、ケースがそうでないことを示しているため、ユニットインスタンスが選択できないことではなく、逆シリアル化されたインスタンスが元のインスタンスと等しくないため、同等であっても互換性のないユニットとして扱われることではないようです。

以前にユニットを使用したことはありませんが、ソースをざっと調べた後、問題はunits.compatibility.compatible両方のインスタンスが等しいかどうかをチェックすることですが、LeafUnitもそのベースも__eq__メソッドを定義しているため、代わりにオブジェクトのアイデンティティがチェックされるようです(pythonのセマンティクスによる)。

つまり、2 つのユニット インスタンスは、2 つの同等のインスタンスではなく、同じインスタンス (同じメモリ アドレスなど) である場合にのみ等しいと比較されます通常、シリアル化されたインスタンスを unpickle すると、元のインスタンスと同じインスタンスにはなりません (同等ですが、同じではありません)。

解決策は、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 に答える