I was trying to parse a string with a temperature and pint fails due to the non-multiplicative nature of the temperature. However, it seems the internal conversion should handle this:
from pint import Quantity
Quantity("6degC")
Produces
---------------------------------------------------------------------------
OffsetUnitCalculusError Traceback (most recent call last)
Cell In[6], line 1
----> 1 Quantity("6degC")
File ~/virtual_enviroments/cfd-2d/lib/python3.10/site-packages/pint/facets/plain/quantity.py:199, in PlainQuantity.__new__(cls, value, units)
197 if units is None and isinstance(value, str):
198 ureg = SharedRegistryObject.__new__(cls)._REGISTRY
--> 199 inst = ureg.parse_expression(value)
200 return cls.__new__(cls, inst)
202 if units is None and isinstance(value, cls):
File ~/virtual_enviroments/cfd-2d/lib/python3.10/site-packages/pint/facets/plain/registry.py:1398, in GenericPlainRegistry.parse_expression(self, input_string, case_sensitive, **values)
1395 def _define_op(s: str):
1396 return self._eval_token(s, case_sensitive=case_sensitive, **values)
-> 1398 return build_eval_tree(gen).evaluate(_define_op)
File ~/virtual_enviroments/cfd-2d/lib/python3.10/site-packages/pint/pint_eval.py:382, in EvalTreeNode.evaluate(self, define_op, bin_op, un_op)
379 if op_text not in bin_op:
380 raise DefinitionSyntaxError(f"missing binary operator '{op_text}'")
--> 382 return bin_op[op_text](
383 self.left.evaluate(define_op, bin_op, un_op),
384 self.right.evaluate(define_op, bin_op, un_op),
385 )
386 elif self.operator:
387 assert isinstance(self.left, EvalTreeNode), "self.left not EvalTreeNode (4)"
File ~/virtual_enviroments/cfd-2d/lib/python3.10/site-packages/pint/facets/plain/quantity.py:1018, in PlainQuantity.__mul__(self, other)
1017 def __mul__(self, other):
-> 1018 return self._mul_div(other, operator.mul)
File ~/virtual_enviroments/cfd-2d/lib/python3.10/site-packages/pint/facets/plain/quantity.py:101, in check_implemented.<locals>.wrapped(self, *args, **kwargs)
99 elif isinstance(other, list) and other and isinstance(other[0], type(self)):
100 return NotImplemented
--> 101 return f(self, *args, **kwargs)
File ~/virtual_enviroments/cfd-2d/lib/python3.10/site-packages/pint/facets/plain/quantity.py:75, in ireduce_dimensions.<locals>.wrapped(self, *args, **kwargs)
74 def wrapped(self, *args, **kwargs):
---> 75 result = f(self, *args, **kwargs)
76 try:
77 if result._REGISTRY.autoconvert_to_preferred:
File ~/virtual_enviroments/cfd-2d/lib/python3.10/site-packages/pint/facets/plain/quantity.py:966, in PlainQuantity._mul_div(self, other, magnitude_op, units_op)
964 if not self._check(other):
965 if not self._ok_for_muldiv(no_offset_units_self):
--> 966 raise OffsetUnitCalculusError(self._units, getattr(other, "units", ""))
967 if len(offset_units_self) == 1:
968 if self._units[offset_units_self[0]] != 1 or magnitude_op not in (
969 operator.mul,
970 operator.imul,
971 ):
OffsetUnitCalculusError: Ambiguous operation with offset unit (degree_Celsius). See https://pint.readthedocs.io/en/stable/user/nonmult.html for guidance.
However this works
Quantity(6, "degC")
<Quantity(6, 'degree_Celsius')>
So this should be the parsing path taken internally. Or am I seeing this wrongly?
Pint since version 0.6 no longer supports that syntax. Units with offset must be explicitly created eg Quantity(6, "degC")
instead of Quantity("6degC")
To get the behaviour you want, do
from pint import UnitRegistry
ureg = UnitRegistry(autoconvert_offset_to_baseunit=True)
ureg.Quantity("6degC")
6 degree_Celsius
I like how it was explained here