Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to pickle python "units" units?

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

like image 590
woodardj Avatar asked Dec 05 '25 19:12

woodardj


1 Answers

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".

like image 155
albertov Avatar answered Dec 08 '25 10:12

albertov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!