I would like to suggest an adaptation of @whereisalext's answer. By creating a dict of supported units with their respective sizes and then iterating from larger to smaller, the same behaviour can be achieved with less code:
def humanbytes(num_bytes: int) -> str:
"""Return the given bytes as a human friendly B, KB, MB, GB, or TB string."""
units_map = {
'TB': 2**40,
'GB': 2**30,
'MB': 2**20,
'KB': 2**10,
'B': 1,
}
# determine unit and factor
for unit_name, unit_factor in units_map.items():
if unit_factor <= num_bytes:
break
# build response
return f'{float(num_bytes/unit_factor):.2f} {unit_name}'
Output:
1 == 1.00 B
1024 == 1.00 KB
500000 == 488.28 KB
1048576 == 1.00 MB
50000000 == 47.68 MB
1073741824 == 1.00 GB
5000000000 == 4.66 GB
1099511627776 == 1.00 TB
5000000000000 == 4.55 TB