quantiphy
quantiphy copied to clipboard
KeyError using binary scales when binary=True
I'm getting KeyError '' when trying to scale using a binary quantity:
>>> from quantiphy import Quantity
>>> i=Quantity(100.0, binary=True)
>>> print(i.binary(scale='Mi'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<redacted>/venv/lib/python3.11/site-packages/quantiphy/quantiphy.py", line 2382, in binary
number, units = _scale(scale, self)
^^^^^^^^^^^^^^^^^^^
File "<redacted>/venv/lib/python3.11/site-packages/quantiphy/quantiphy.py", line 74, in _scale
scaled = UnitConversion._convert_units(scale, unscaled.units, unscaled)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<redacted>/venv/lib/python3.11/site-packages/quantiphy/quantiphy.py", line 3614, in _convert_units
to_units, from_units, to_sf, from_sf = get_converter(to_units, from_units)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<redacted>/venv/lib/python3.11/site-packages/quantiphy/quantiphy.py", line 3610, in get_converter
return to_units, from_units, get_sf(to_sf), get_sf(from_sf)
^^^^^^^^^^^^^^^
File "<redacted>/venv/lib/python3.11/site-packages/quantiphy/quantiphy.py", line 3607, in get_sf
return float('1' + MAPPINGS[sf])
~~~~~~~~^^^^
KeyError: ''
"i.render(scale='Mi')" produces the same error.
Quantiphy has limited support for scaling with scale factors, and it at this point it does not extend to the binary scale factors.
Can I ask what you are trying to accomplish?
I have a list of numbers which can vary from very high to very low, but which I would like to render with the same base, .e.g. "Mi", so that it is easier to see the differences when rendered. When rendering numbers with the default setting, the numbers are auto-scaled and so the user have to do a mental calculation: "is 1.25GB higher or lower than 2.1MB?". I use non-binary scale "M" as a workaround, which works.
There are two points here:
- the documentation states binary scaling should work when binary=True: "* binary (bool) – Allow use of binary scale factors (Ki, Mi, Gi, Ti, Pi, Ei, Zi, Yi)." (https://quantiphy.readthedocs.io/en/stable/api.html#quantiphy.Quantity.render), and
- the error message is unhelpful. It should preferably raise a "ValueError" or similar with "unrecognized scale 'Mi'" information, not KeyError, which is an internal error.
Though I am not familiar with the code, at a glance it seems the code should check MAPPINGS, and then also BINARY_MAPPINGS when binary=True?
Other than this, it works great, thank you!
Thanks, that was very helpful.
I have pushed a fix to GitHub. Would you be able to try it and let me know if it meets your needs.
Here is a fixed-up version of your example:
>>> from quantiphy import Quantity
>>> b = Quantity(1000, 'B')
>>> print(b.fixed(scale='MiB')
0.001 MiB
Notice I did not specify the binary keyword argument to Quantity. It is only needed if the first argument, the value, is given as a string that employs a binary scale factor.
Also notice that I used fixed rather than binary or render to print the value, which would result in the value having two scale factors.
If you want the difference in scale between the values in a table very obvious, you might try something like this:
>>> bytes = [Quantity(l, binary=True) for l in '1B 1KiB 1MiB 1GiB 1TiB'.split()]
>>> with Quantity.prefs(prec=6, number_fmt='{whole:>8}{frac:<7} {units}'):
... for b in bytes:
... print(b.fixed(scale='MiB'))
0.000001 MiB
0.000977 MiB
1 MiB
1024 MiB
1048576 MiB
Thanks, that looks awesome. I will try to test it some time this week.