我正在使用一个读取文件并返回其大小(以字节为单位)的库。
然后,该文件大小将显示给最终用户。使他们更容易理解它,我明确的文件大小转换为MB
通过将其除以1024.0 * 1024.0
。当然可以,但是我想知道在Python中还有更好的方法吗?
更好的是,我的意思是也许一个stdlib函数可以根据我想要的类型操纵大小。就像我指定的一样MB
,它会自动将其除以1024.0 * 1024.0
。这些线路上有一些东西。
我正在使用一个读取文件并返回其大小(以字节为单位)的库。
然后,该文件大小将显示给最终用户。使他们更容易理解它,我明确的文件大小转换为MB
通过将其除以1024.0 * 1024.0
。当然可以,但是我想知道在Python中还有更好的方法吗?
更好的是,我的意思是也许一个stdlib函数可以根据我想要的类型操纵大小。就像我指定的一样MB
,它会自动将其除以1024.0 * 1024.0
。这些线路上有一些东西。
kB (Kilo) for 1.000 Byte
and KiB (Kibi) for 1.024 Byte
。参见en.wikipedia.org/wiki/Kibibyte。
Answers:
有hurry.filesize,它将以字节为单位,如果有的话,将做出一个漂亮的字符串。
>>> from hurry.filesize import size
>>> size(11000)
'10K'
>>> size(198283722)
'189M'
或者,如果您希望1K == 1000(这是大多数用户的假设):
>>> from hurry.filesize import size, si
>>> size(11000, system=si)
'11K'
>>> size(198283722, system=si)
'198M'
它也具有IEC支持(但是没有记录):
>>> from hurry.filesize import size, iec
>>> size(11000, system=iec)
'10Ki'
>>> size(198283722, system=iec)
'189Mi'
因为它是由Awesome Martijn Faassen编写的,所以代码小巧,清晰且可扩展。编写自己的系统非常容易。
这是一个:
mysystem = [
(1024 ** 5, ' Megamanys'),
(1024 ** 4, ' Lotses'),
(1024 ** 3, ' Tons'),
(1024 ** 2, ' Heaps'),
(1024 ** 1, ' Bunches'),
(1024 ** 0, ' Thingies'),
]
像这样使用:
>>> from hurry.filesize import size
>>> size(11000, system=mysystem)
'10 Bunches'
>>> size(198283722, system=mysystem)
'189 Heaps'
1024
(整数)。
MBFACTOR = float(1 << 20); mb= int(size_in_bytes) / MBFACTOR
@LennartRegebro
这是我用的:
import math
def convert_size(size_bytes):
if size_bytes == 0:
return "0B"
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
i = int(math.floor(math.log(size_bytes, 1024)))
p = math.pow(1024, i)
s = round(size_bytes / p, 2)
return "%s %s" % (s, size_name[i])
注意:大小应以字节为单位发送。
除了使用大小除数,1024 * 1024
还可以使用<<
按位移位运算符,例如1<<20
,获取兆字节,1<<30
获取千兆字节等。
在最简单的情况下,您可以具有例如MBFACTOR = float(1<<20)
可以与字节一起使用的常量,即:megas = size_in_bytes/MBFACTOR
。
通常只需要兆字节,否则可以使用如下所示的内容:
# bytes pretty-printing
UNITS_MAPPING = [
(1<<50, ' PB'),
(1<<40, ' TB'),
(1<<30, ' GB'),
(1<<20, ' MB'),
(1<<10, ' KB'),
(1, (' byte', ' bytes')),
]
def pretty_size(bytes, units=UNITS_MAPPING):
"""Get human-readable file sizes.
simplified version of https://pypi.python.org/pypi/hurry.filesize/
"""
for factor, suffix in units:
if bytes >= factor:
break
amount = int(bytes / factor)
if isinstance(suffix, tuple):
singular, multiple = suffix
if amount == 1:
suffix = singular
else:
suffix = multiple
return str(amount) + suffix
print(pretty_size(1))
print(pretty_size(42))
print(pretty_size(4096))
print(pretty_size(238048577))
print(pretty_size(334073741824))
print(pretty_size(96995116277763))
print(pretty_size(3125899904842624))
## [Out] ###########################
1 byte
42 bytes
4 KB
227 MB
311 GB
88 TB
2 PB
>>
吗
0
。
这是计算尺寸的紧凑函数
def GetHumanReadable(size,precision=2):
suffixes=['B','KB','MB','GB','TB']
suffixIndex = 0
while size > 1024 and suffixIndex < 4:
suffixIndex += 1 #increment the index of the suffix
size = size/1024.0 #apply the division
return "%.*f%s"%(precision,size,suffixes[suffixIndex])
有关更详细的输出(反之亦然)的操作,请参阅:http : //code.activestate.com/recipes/578019-bytes-to-human-human-to-bytes-converter/
如果您已经知道所需的内容,请参见下文,以一种快速且相对易于阅读的方式在一行代码中打印文件大小。这些单行代码将上述@ccpizza的出色答案与一些方便的格式化技巧结合在一起,我在这里阅读了如何将带有逗号的数字打印为数千个分隔符?。
print ('{:,.0f}'.format(os.path.getsize(filepath))+" B")
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<7))+" kb")
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<10))+" KB")
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<17))+" mb")
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<20))+" MB")
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<27))+" gb")
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<30))+" GB")
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<40))+" TB")
显然,他们假设您一开始就大致知道要处理的大小,在我的案例(西南伦敦电视台的视频编辑器)中,视频剪辑的大小为MB,有时为GB。
使用PATHLIB更新 为了回应Hildy的评论,以下是我的建议:仅使用Python标准库提供一对紧凑的函数(保持事物为“原子的”而不是合并它们):
from pathlib import Path
def get_size(path = Path('.')):
""" Gets file size, or total directory size """
if path.is_file():
size = path.stat().st_size
elif path.is_dir():
size = sum(file.stat().st_size for file in path.glob('*.*'))
return size
def format_size(path, unit="MB"):
""" Converts integers to common size units used in computing """
bit_shift = {"B": 0,
"kb": 7,
"KB": 10,
"mb": 17,
"MB": 20,
"gb": 27,
"GB": 30,
"TB": 40,}
return "{:,.0f}".format(get_size(path) / float(1 << bit_shift[unit])) + " " + unit
# Tests and test results
>>> format_size("d:\\media\\bags of fun.avi")
'38 MB'
>>> format_size("d:\\media\\bags of fun.avi","KB")
'38,763 KB'
>>> format_size("d:\\media\\bags of fun.avi","kb")
'310,104 kb'
以防万一有人在寻找这个问题的反面(就像我确定的那样),这对我有用:
def get_bytes(size, suffix):
size = int(float(size))
suffix = suffix.lower()
if suffix == 'kb' or suffix == 'kib':
return size << 10
elif suffix == 'mb' or suffix == 'mib':
return size << 20
elif suffix == 'gb' or suffix == 'gib':
return size << 30
return False
<< 10
来* 1024
,<< 20
来* 1024**2
和<< 30
到* 1024**3
。
这是我的两分钱,可以上下浮动,并增加了可自定义的精度:
def convertFloatToDecimal(f=0.0, precision=2):
'''
Convert a float to string of decimal.
precision: by default 2.
If no arg provided, return "0.00".
'''
return ("%." + str(precision) + "f") % f
def formatFileSize(size, sizeIn, sizeOut, precision=0):
'''
Convert file size to a string representing its value in B, KB, MB and GB.
The convention is based on sizeIn as original unit and sizeOut
as final unit.
'''
assert sizeIn.upper() in {"B", "KB", "MB", "GB"}, "sizeIn type error"
assert sizeOut.upper() in {"B", "KB", "MB", "GB"}, "sizeOut type error"
if sizeIn == "B":
if sizeOut == "KB":
return convertFloatToDecimal((size/1024.0), precision)
elif sizeOut == "MB":
return convertFloatToDecimal((size/1024.0**2), precision)
elif sizeOut == "GB":
return convertFloatToDecimal((size/1024.0**3), precision)
elif sizeIn == "KB":
if sizeOut == "B":
return convertFloatToDecimal((size*1024.0), precision)
elif sizeOut == "MB":
return convertFloatToDecimal((size/1024.0), precision)
elif sizeOut == "GB":
return convertFloatToDecimal((size/1024.0**2), precision)
elif sizeIn == "MB":
if sizeOut == "B":
return convertFloatToDecimal((size*1024.0**2), precision)
elif sizeOut == "KB":
return convertFloatToDecimal((size*1024.0), precision)
elif sizeOut == "GB":
return convertFloatToDecimal((size/1024.0), precision)
elif sizeIn == "GB":
if sizeOut == "B":
return convertFloatToDecimal((size*1024.0**3), precision)
elif sizeOut == "KB":
return convertFloatToDecimal((size*1024.0**2), precision)
elif sizeOut == "MB":
return convertFloatToDecimal((size*1024.0), precision)
根据需要添加TB
,等等。
这是与ls -lh输出匹配的版本。
def human_size(num: int) -> str:
base = 1
for unit in ['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']:
n = num / base
if n < 9.95 and unit != 'B':
# Less than 10 then keep 1 decimal place
value = "{:.1f}{}".format(n, unit)
return value
if round(n) < 1000:
# Less than 4 digits so use this
value = "{}{}".format(round(n), unit)
return value
base *= 1024
value = "{}{}".format(round(n), unit)
return value
UNITS = {1000: ['KB', 'MB', 'GB'],
1024: ['KiB', 'MiB', 'GiB']}
def approximate_size(size, flag_1024_or_1000=True):
mult = 1024 if flag_1024_or_1000 else 1000
for unit in UNITS[mult]:
size = size / mult
if size < mult:
return '{0:.3f} {1}'.format(size, unit)
approximate_size(2123, False)
这是我的实现:
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)
它将最多打印三个小数,并去除尾随的零和句点。布尔参数si
将切换基于10和2的大小量级的用法。
这是它的对应物。它允许编写干净的配置文件,如{'maximum_filesize': from_filesize('10M')
。它返回一个近似于预期文件大小的整数。我没有使用移位,因为源值是一个浮点数(它将接受from_filesize('2.15M')
就可以了)。将其转换为整数/小数虽然可以,但是会使代码更加复杂,并且已经可以正常使用了。
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)
这是@romeo的反向实现的另一个版本,它处理单个输入字符串。
import re
def get_bytes(size_string):
try:
size_string = size_string.lower().replace(',', '')
size = re.search('^(\d+)[a-z]i?b$', size_string).groups()[0]
suffix = re.search('^\d+([kmgtp])i?b$', size_string).groups()[0]
except AttributeError:
raise ValueError("Invalid Input")
shft = suffix.translate(str.maketrans('kmgtp', '12345')) + '0'
return int(size) << int(shft)
类似于亚伦·杜克(Aaron Duke)的答复,但更多的是“ pythonic”;)
import re
RE_SIZE = re.compile(r'^(\d+)([a-z])i?b?$')
def to_bytes(s):
parts = RE_SIZE.search(s.lower().replace(',', ''))
if not parts:
raise ValueError("Invalid Input")
size = parts.group(1)
suffix = parts.group(2)
shift = suffix.translate(str.maketrans('kmgtp', '12345')) + '0'
return int(size) << int(shift)
我是编程新手。我想出了以下函数,它将给定的文件大小转换为可读格式。
def file_size_converter(size):
magic = lambda x: str(round(size/round(x/1024), 2))
size_in_int = [int(1 << 10), int(1 << 20), int(1 << 30), int(1 << 40), int(1 << 50)]
size_in_text = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
for i in size_in_int:
if size < i:
g = size_in_int.index(i)
position = int((1024 % i) / 1024 * g)
ss = magic(i)
return ss + ' ' + size_in_text[position]
这适用于所有文件大小:
import math
from os.path import getsize
def convert_size(size):
if (size == 0):
return '0B'
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
i = int(math.floor(math.log(size,1024)))
p = math.pow(1024,i)
s = round(size/p,2)
return '%s %s' % (s,size_name[i])
print(convert_size(getsize('file_name.zip')))