Created
June 17, 2021 17:15
-
-
Save rgkimball/d3301af7a6993c62442685a063632502 to your computer and use it in GitHub Desktop.
Human-readable Size
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def readable_size(byte_size: int, base: int = 10, decimals: int = 1): | |
""" | |
Given the size of an object in bytes, returns a human-readable alternative. | |
For ex: | |
>>> readable_size(44000000) | |
42.0 MB | |
Supports sizes up to 1024 yobibytes in Binary or 1000 yottabytes in Decimal SI. | |
Inspired by the following StackOverflow questions: | |
- https://stackoverflow.com/questions/1094841/get-human-readable-version-of-file-size | |
- https://stackoverflow.com/questions/3758606/how-can-i-convert-byte-size-into-a-human-readable-format-in-java | |
:param byte_size: the size of the object in bytes | |
:param base: optional int, either 2 for Binary or 10 for Decimal SI. Binary is the default. | |
:param decimals: optional int, specify the number of significant digits to return | |
:return: str formatted with the maximum possible units and the suffix, like '50.0 MiB' | |
""" | |
if base == 2: | |
unit, pre = 2 ** 10, 'kMGTPEZY' | |
elif base == 10: | |
unit, pre = 10 ** 3, 'KMGTPEZY' | |
else: | |
raise ValueError('Base must either be 10 or 2; given: {0}'.format(base)) | |
abs_bytes = abs(byte_size) | |
if abs_bytes < unit: | |
return '{0:.1f} B'.format(byte_size) | |
exp = int(math.log(abs_bytes) / math.log(unit)) | |
th = math.ceil(math.pow(unit, exp) * (unit - 0.05)) | |
if exp < 6 and abs_bytes >= th - (51 if (th & 0xFFF) == 0xD00 else 0): | |
exp += 1 | |
suffix = pre[exp - 1] | |
# Discard significant digits to improve floating point precision of really large values when printing | |
if exp > 4: | |
byte_size /= unit | |
exp -= 1 | |
return '{0:.{3}f} {1}{2}B'.format(byte_size / math.pow(unit, exp), suffix, 'i' if base == 2 else '', decimals) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment