我正在尝试编写一个应用程序,将字节转换为kb到mb到gb到tb。这是我到目前为止所拥有的:
def size_format(b):
if b < 1000:
return '%i' % b + 'B'
elif 1000 <= b < 1000000:
return '%.1f' % float(b/1000) + 'KB'
elif 1000000 <= b < 1000000000:
return '%.1f' % float(b/1000000) + 'MB'
elif 1000000000 <= b < 1000000000000:
return '%.1f' % float(b/1000000000) + 'GB'
elif 1000000000000 <= b:
return '%.1f' % float(b/1000000000000) + 'TB'
问题是,当我尝试应用程序时,我会在十进制清零后得到所有内容。例如size_format(623)
产生'623B',但是使用size_format(6200)
,而不是得到'6.2kb',我得到'6.0kb'。有什么想法吗?
修正了Bryan_Rch的答案:
def format_bytes(size):
# 2**10 = 1024
power = 2**10
n = 0
power_labels = {0 : '', 1: 'kilo', 2: 'mega', 3: 'giga', 4: 'tera'}
while size > power:
size /= power
n += 1
return size, power_labels[n]+'bytes'
在分割之前浮动(b),例如做float(b)/1000
而不是float(b/1000)
,因为b
和1000都是整数,b/1000
仍然是一个没有小数部分的整数。
这是将字节转换为kilo,mega,tera。
#From bytes to kilo, mega, tera
def get_(size):
#2**10 = 1024
power = 2**10
n = 1
Dic_powerN = {1:'kilobytes', 2:'megabytes', 3:'gigabytes', 4:'Terabytes'}
if size <= power**2 :
size /= power
return size, Dic_powerN[n]
else:
while size > power :
n += 1
size /= power**n
return size, Dic_powerN[n]
没有小数位的输出:
>>> format_file_size(12345678)
'11 MiB, 792 KiB, 334 bytes'
format_file_size(
def format_file_size(fsize):
result = []
units = {s: u for s, u in zip(reversed([2 ** n for n in range(0, 40, 10)]), ['GiB', 'MiB', 'KiB', 'bytes'])}
for s, u in units.items():
t = fsize // s
if t > 0:
result.append('{} {}'.format(t, u))
fsize = fsize % s
return ', '.join(result) or '0 bytes'
def humanbytes(B):
'Return the given bytes as a human friendly KB, MB, GB, or TB string'
B = float(B)
KB = float(1024)
MB = float(KB ** 2) # 1,048,576
GB = float(KB ** 3) # 1,073,741,824
TB = float(KB ** 4) # 1,099,511,627,776
if B < KB:
return '{0} {1}'.format(B,'Bytes' if 0 == B > 1 else 'Byte')
elif KB <= B < MB:
return '{0:.2f} KB'.format(B/KB)
elif MB <= B < GB:
return '{0:.2f} MB'.format(B/MB)
elif GB <= B < TB:
return '{0:.2f} GB'.format(B/GB)
elif TB <= B:
return '{0:.2f} TB'.format(B/TB)
tests = [1, 1024, 500000, 1048576, 50000000, 1073741824, 5000000000, 1099511627776, 5000000000000]
for t in tests: print '{0} == {1}'.format(t,humanbytes(t))
输出:
1 == 1.0 Byte
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
对于未来我来说,它也在Perl中:
sub humanbytes {
my $B = shift;
my $KB = 1024;
my $MB = $KB ** 2; # 1,048,576
my $GB = $KB ** 3; # 1,073,741,824
my $TB = $KB ** 4; # 1,099,511,627,776
if ($B < $KB) {
return "$B " . (($B == 0 || $B > 1) ? 'Bytes' : 'Byte');
} elsif ($B >= $KB && $B < $MB) {
return sprintf('%0.02f',$B/$KB) . ' KB';
} elsif ($B >= $MB && $B < $GB) {
return sprintf('%0.02f',$B/$MB) . ' MB';
} elsif ($B >= $GB && $B < $TB) {
return sprintf('%0.02f',$B/$GB) . ' GB';
} elsif ($B >= $TB) {
return sprintf('%0.02f',$B/$TB) . ' TB';
}
}
我有相当可读的功能将字节转换为更大的单位:
def bytes_2_human_readable(number_of_bytes):
if number_of_bytes < 0:
raise ValueError("!!! number_of_bytes can't be smaller than 0 !!!")
step_to_greater_unit = 1024.
number_of_bytes = float(number_of_bytes)
unit = 'bytes'
if (number_of_bytes / step_to_greater_unit) >= 1:
number_of_bytes /= step_to_greater_unit
unit = 'KB'
if (number_of_bytes / step_to_greater_unit) >= 1:
number_of_bytes /= step_to_greater_unit
unit = 'MB'
if (number_of_bytes / step_to_greater_unit) >= 1:
number_of_bytes /= step_to_greater_unit
unit = 'GB'
if (number_of_bytes / step_to_greater_unit) >= 1:
number_of_bytes /= step_to_greater_unit
unit = 'TB'
precision = 1
number_of_bytes = round(number_of_bytes, precision)
return str(number_of_bytes) + ' ' + unit
另一个manbytes版本,没有循环/ if..else,在python3语法中。
从@ whereisalext的答案中窃取的测试号码。
请注意,它仍然是草图,例如如果数字足够大,它将追溯。
import math as m
MULTIPLES = ["B", "k{}B", "M{}B", "G{}B", "T{}B", "P{}B", "E{}B", "Z{}B", "Y{}B"]
def humanbytes(i, binary=False, precision=2):
base = 1024 if binary else 1000
multiple = m.trunc(m.log2(i) / m.log2(base))
value = i / m.pow(base, multiple)
suffix = MULTIPLES[multiple].format("i" if binary else "")
return f"{value:.{precision}f} {suffix}"
if __name__ == "__main__":
sizes = [
1, 1024, 500000, 1048576, 50000000, 1073741824, 5000000000,
1099511627776, 5000000000000]
for i in sizes:
print(f"{i} == {humanbytes(i)}, {humanbytes(i, binary=True)}")
结果:
1 == 1.00 B, 1.00 B
1024 == 1.02 kB, 1.00 kiB
500000 == 500.00 kB, 488.28 kiB
1048576 == 1.05 MB, 1.00 MiB
50000000 == 50.00 MB, 47.68 MiB
1073741824 == 1.07 GB, 1.00 GiB
5000000000 == 5.00 GB, 4.66 GiB
1099511627776 == 1.10 TB, 1.00 TiB
5000000000000 == 5.00 TB, 4.55 TiB
您可以更改分部的行为,而不是修改代码:
from __future__ import division
这提供了Python 2.x使用的“经典”风格的“真正”划分。有关详细信息,请参阅PEP 238 - Changing the Division Operator。
现在这是Python 3.x中的默认行为
这是一个紧凑的版本,它将B(字节)转换为任何更高的顺序,如MB,GB,而不在python中使用大量的if...else
。我用bit-wise来处理这个问题。如果在函数中触发参数return_output
为True,它还允许返回浮点输出:
import math
def bytes_conversion(number, return_float=False):
def _conversion(number, return_float=False):
length_number = int(math.log10(number))
if return_float:
length_number = int(math.log10(number))
return length_number // 3, '%.2f' % (int(number)/(1 << (length_number//3) *10))
return length_number // 3, int(number) >> (length_number//3) * 10
unit_dict = {
0: "B", 1: "kB",
2: "MB", 3: "GB",
4: "TB", 5: "PB",
6: "EB"
}
if return_float:
num_length, number = _conversion(number, return_float=return_float)
else:
num_length, number = _conversion(number)
return "%s %s" % (number, unit_dict[num_length])
#Example usage:
#print(bytes_conversion(491266116, return_float=True))
这只是我在StackOverflow中的一些帖子。如果我有任何错误或违规行为,请通知我。
对我来说好主意:
def convert_bytes(num):
"""
this function will convert bytes to MB.... GB... etc
"""
step_unit = 1000.0 #1024 bad the size
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
if num < step_unit:
return "%3.1f %s" % (num, x)
num /= step_unit
当您使用整数除法划分值时,因为两个值都是整数。您需要先将其中一个转换为float:
return '%.1f' % float(b)/1000 + 'KB'
甚至只是
return '%.1f' % b/1000.0 + 'KB'
在我看来,我已经改进了@whereisalext的答案,它有一个更通用的函数,它不再需要添加更多if语句,而是再次添加单元:
AVAILABLE_UNITS = ['bytes', 'KB', 'MB', 'GB', 'TB']
def get_amount_and_unit(byte_amount):
for index, unit in enumerate(AVAILABLE_UNITS):
lower_threshold = 0 if index == 0 else 1024 ** (index - 1)
upper_threshold = 1024 ** index
if lower_threshold <= byte_amount < upper_threshold:
if lower_threshold == 0:
return byte_amount, unit
else:
return byte_amount / lower_threshold, AVAILABLE_UNITS[index - 1]
# Default to the maximum
max_index = len(AVAILABLE_UNITS) - 1
return byte_amount / (1024 ** max_index), AVAILABLE_UNITS[max_index]
请注意,这与@ whereisalext的算法略有不同: