Here is my implementation:
from bisect import bisect
def to_filesize(bytes_num, si=True):
decade = 1000 if si else 1024
partitions = tuple(decade ** n for n in range(1, 6))
suffixes = tuple('BKMGTP')
i = bisect(partitions, bytes_num)
s = suffixes[i]
for n in range(i):
bytes_num /= decade
f = '{:.3f}'.format(bytes_num)
return '{}{}'.format(f.rstrip('0').rstrip('.'), s)
It will print up to three decimals and it strips trailing zeros and periods. The boolean parameter si
will toggle usage of 10-based vs. 2-based size magnitude.
This is its counterpart. It allows to write clean configuration files like {'maximum_filesize': from_filesize('10M')
. It returns an integer that approximates the intended filesize. I am not using bit shifting because the source value is a floating point number (it will accept from_filesize('2.15M')
just fine). Converting it to an integer/decimal would work but makes the code more complicated and it already works as it is.
def from_filesize(spec, si=True):
decade = 1000 if si else 1024
suffixes = tuple('BKMGTP')
num = float(spec[:-1])
s = spec[-1]
i = suffixes.index(s)
for n in range(i):
num *= decade
return int(num)