从字节大小返回人类可读大小的函数:
>>> human_readable(2048)
'2 kilobytes'
>>>
如何做到这一点?
从字节大小返回人类可读大小的函数:
>>> human_readable(2048)
'2 kilobytes'
>>>
如何做到这一点?
当前回答
使用1000或kibibytes的幂将更符合标准:
def sizeof_fmt(num, use_kibibyte=True):
base, suffix = [(1000.,'B'),(1024.,'iB')][use_kibibyte]
for x in ['B'] + map(lambda x: x+suffix, list('kMGTP')):
if -base < num < base:
return "%3.1f %s" % (num, x)
num /= base
return "%3.1f %s" % (num, x)
附注:永远不要相信一个以K(大写)后缀打印数千的库。
其他回答
“人类友好”项目有助于解决这一问题。
import humanfriendly
humanfriendly.format_size(1024)
上面的代码将给出1KB的答案。 例子可以在这里找到。
根据之前所有的答案,以下是我的看法。它是一个以字节为单位以整数形式存储文件大小的对象。但是当你尝试打印对象时,你会自动得到一个人类可读的版本。
class Filesize(object):
"""
Container for a size in bytes with a human readable representation
Use it like this::
>>> size = Filesize(123123123)
>>> print size
'117.4 MB'
"""
chunk = 1024
units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
precisions = [0, 0, 1, 2, 2, 2]
def __init__(self, size):
self.size = size
def __int__(self):
return self.size
def __str__(self):
if self.size == 0: return '0 bytes'
from math import log
unit = self.units[min(int(log(self.size, self.chunk)), len(self.units) - 1)]
return self.format(unit)
def format(self, unit):
if unit not in self.units: raise Exception("Not a valid file size unit: %s" % unit)
if self.size == 1 and unit == 'bytes': return '1 byte'
exponent = self.units.index(unit)
quotient = float(self.size) / self.chunk**exponent
precision = self.precisions[exponent]
format_string = '{:.%sf} {}' % (precision)
return format_string.format(quotient, unit)
为了以人类可读的形式获取文件大小,我创建了这个函数:
import os
def get_size(path):
size = os.path.getsize(path)
if size < 1024:
return f"{size} bytes"
elif size < pow(1024,2):
return f"{round(size/1024, 2)} KB"
elif size < pow(1024,3):
return f"{round(size/(pow(1024,2)), 2)} MB"
elif size < pow(1024,4):
return f"{round(size/(pow(1024,3)), 2)} GB"
>>> get_size("a.txt")
1.4KB
您将在下面发现的决不是已经发布的解决方案中性能最好或最短的解决方案。相反,它专注于一个许多其他答案都忽略的特定问题。
即输入如999_995时的情况:
Python 3.6.1 ...
...
>>> value = 999_995
>>> base = 1000
>>> math.log(value, base)
1.999999276174054
哪个,被截断为最近的整数,并应用回输入给出
>>> order = int(math.log(value, base))
>>> value/base**order
999.995
这似乎正是我们所期望的,直到我们被要求控制输出精度。这就是事情开始变得有点困难的时候。
将精度设置为2位,我们得到:
>>> round(value/base**order, 2)
1000 # K
而不是1M。
我们该如何应对呢?
当然,我们可以显式地检查它:
if round(value/base**order, 2) == base:
order += 1
但我们能做得更好吗?在我们做最后一步之前,我们能知道订单应该怎么削减吗?
事实证明我们可以。
假设0.5十进制舍入规则,则上述if条件转化为:
导致
def abbreviate(value, base=1000, precision=2, suffixes=None):
if suffixes is None:
suffixes = ['', 'K', 'M', 'B', 'T']
if value == 0:
return f'{0}{suffixes[0]}'
order_max = len(suffixes) - 1
order = log(abs(value), base)
order_corr = order - int(order) >= log(base - 0.5/10**precision, base)
order = min(int(order) + order_corr, order_max)
factored = round(value/base**order, precision)
return f'{factored:,g}{suffixes[order]}'
给
>>> abbreviate(999_994)
'999.99K'
>>> abbreviate(999_995)
'1M'
>>> abbreviate(999_995, precision=3)
'999.995K'
>>> abbreviate(2042, base=1024)
'1.99K'
>>> abbreviate(2043, base=1024)
'2K'
如果有人想知道,要将@Sridhar Ratnakumar的答案转换回字节,您可以执行以下操作:
import math
def format_back_to_bytes(value):
for power, unit in enumerate(["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]):
if value[-3:-1] == unit:
return round(float(value[:-3])*math.pow(2, 10*power))
用法:
>>> format_back_to_bytes('212.4GiB')
228062763418