The following code prints '1 dimensionless':
import pint
ureg=pint.UnitRegistry()
print(ureg(0.))
Why, Pint?
On
looks like a bug/limitation in the package.
When passing an integer (different from 0) pint crashes:
>>> ureg(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python34\lib\site-packages\pint\registry.py", line 837, in parse_expression
input_string = string_preprocessor(input_string)
File "C:\Python34\lib\site-packages\pint\util.py", line 579, in string_preprocessor
input_string = input_string.replace(",", "")
AttributeError: 'int' object has no attribute 'replace'
in registry.py
def parse_expression(self, input_string, case_sensitive=True, **values):
"""Parse a mathematical expression including units and return a quantity object.
Numerical constants can be specified as keyword arguments and will take precedence
over the names defined in the registry.
"""
if not input_string:
return self.Quantity(1)
input_string = string_preprocessor(input_string) # should not be called with something else than string
it crashes because the package tries to perform string operations on the non-string, where a string is expected. But the test is if not input_string so 0.0 make pint create a 1 class (or whatever that means), just like if you'd pass "". Passing 1 allows to reach the next line, which crashes.
It's just missing a type check, something like:
if not isinstance(input_string,str):
raise Exception("a string is required")
"Calling" a
UnitRegistryobject is equivalent to callingparse_expressionon it.parse_expressionexpects to receive astr, and it has a special case for the empty string, which is to return it as aQuantity(1)(the1 dimensionlessyou see).In this case, you happened to hit a minor flaw in the duck-typing: It expects a string, but doesn't actually verify that it received one. Then it converts any falsy value to
Quantity(1)with the code:so any zero-valued number (or
None, or empty sequence, or other falsy thing) becomesQuantity(1). Had you passed it a truthy expression of an unexpected type, the parser would have gotten involved and raised an exception, but falsy values never even reach the parser.I'm not clear on why the empty expression should be a
Quantity(1), but the authors explicitly put that check in there, so it must have been intended.In short, don't pass non-strings to the function. They'll fail silently when falsy, and raise an exception for anything else (when it assumes they're a
strand it tries to callstrmethods on them).