Similar questions were asked a number of times, but I can share yet another implementation:
from math import log10
KB = 1024
MB = KB * KB
GB = MB * KB
TB = GB * KB
def human_size(s):
"""
>>> human_size(1)
'1 B'
>>> human_size(123)
'123 B'
>>> human_size(1001)
'0.98 KB'
>>> human_size(23456)
'22.9 KB'
"""
units = [(0, 1, "B"), (1000, KB, "KB"), (1000*KB, MB, "MB"),
(1000*MB, GB, "GB"), (1000*GB, TB, "TB")]
for limit, div, unit in reversed(units):
if s > limit:
s = float(s) / div
log = int(log10(s))
if s > 1000:
s = round(s)
else:
norm = 10 ** (log - 2)
s = round(float(s) / norm) * norm
prec = (0 if div == 1 else max(2 - log, 0))
return '%.*f %s' % (prec, s, unit)