在Python中转换文件大小的更好方法

use*_*312 61 python filesize

我正在使用一个读取文件的库,并以字节为单位返回其大小.

然后将此文件大小显示给最终用户; 为了让它们更容易理解它,我明确地将文件大小转换为MB除以1024.0 * 1024.0.当然这有效,但我想知道在Python中有更好的方法吗?

更好的是,我的意思是stdlib函数可以根据我想要的类型操作大小.就像我指定的那样MB,它会自动将其除以1024.0 * 1024.0.有些人在这些方面.

Jam*_*pam 112

这是我使用的:

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])
Run Code Online (Sandbox Code Playgroud)

注意:大小应以字节发送.

  • 如果您以字节为单位发送大小,则只需添加"B"作为size_name的第一个元素. (10认同)
  • 实际上,尺寸名称需要为(“B”、“KiB”、“MiB”、“GiB”、“TiB”、“PiB”、“EiB”、“ZiB”、“YiB”)。请参阅 https://en.wikipedia.org/wiki/Mebibyte 了解更多信息。 (3认同)

Len*_*bro 72

有一个hurry.filesize,它将以字节为单位大小,如果有的话,可以创建一个很好的字符串.

>>> from hurry.filesize import size
>>> size(11000)
'10K'
>>> size(198283722)
'189M'
Run Code Online (Sandbox Code Playgroud)

或者如果你想要1K == 1000(这是大多数用户所假设的):

>>> from hurry.filesize import size, si
>>> size(11000, system=si)
'11K'
>>> size(198283722, system=si)
'198M'
Run Code Online (Sandbox Code Playgroud)

它也有IEC支持(但没有记录):

>>> from hurry.filesize import size, iec
>>> size(11000, system=iec)
'10Ki'
>>> size(198283722, system=iec)
'189Mi'
Run Code Online (Sandbox Code Playgroud)

因为它是由Awesome Martijn Faassen编写的,所以代码很小,清晰且可扩展.编写自己的系统很容易.

这是一个:

mysystem = [
    (1024 ** 5, ' Megamanys'),
    (1024 ** 4, ' Lotses'),
    (1024 ** 3, ' Tons'), 
    (1024 ** 2, ' Heaps'), 
    (1024 ** 1, ' Bunches'),
    (1024 ** 0, ' Thingies'),
    ]
Run Code Online (Sandbox Code Playgroud)

像这样使用:

>>> from hurry.filesize import size
>>> size(11000, system=mysystem)
'10 Bunches'
>>> size(198283722, system=mysystem)
'189 Heaps'
Run Code Online (Sandbox Code Playgroud)

  • 这个包可能很酷,但奇怪的许可证和没有在线可用源代码的事实使它成为我很乐意避免的事情。而且它似乎只支持python2。 (4认同)
  • 嗯,现在我需要一个去另一条路。从“1 kb”到“1024”(一个整数)。 (3认同)
  • 仅适用于 python 2 (2认同)
  • @AlmogCohen 源代码是在线的,可以直接从 PyPI 获得(有些软件包没有 Github 存储库,只有 PyPI 页面),并且许可证并不那么晦涩难懂,ZPL 是 Zope 公共许可证,据我所知,类似 BSD。我确实同意许可本身很奇怪:没有标准的“LICENSE.txt”文件,每个源文件的顶部也没有序言。 (2认同)

ccp*_*zza 25

而不是1024 * 1024你的大小除数可以使用<< 按位移位运算符,即1<<20获得兆字节,1<<30以获得千兆字节等.

我定义了一个常量MBFACTOR = float(1<<20),然后可以用于字节,即:megas = size_in_bytes/MBFACTOR.

  • 不是`>>`? (9认同)
  • @Tjorriemorrie:它必须是左移,右移将丢弃唯一的位并导致“0”。 (2认同)

Pav*_*pta 15

这是计算尺寸的紧凑功能

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])
Run Code Online (Sandbox Code Playgroud)

有关更详细的输出和反之亦然操作,请参阅:http://code.activestate.com/recipes/578019-bytes-to-human-human-to-bytes-converter/


rho*_*hav 10

这里是:

def convert_bytes(size):
    for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
        if size < 1024.0:
            return "%3.1f %s" % (size, x)
        size /= 1024.0

    return size
Run Code Online (Sandbox Code Playgroud)

输出

>>> convert_bytes(1024)
'1.0 KB'
>>> convert_bytes(102400)
'100.0 KB'
Run Code Online (Sandbox Code Playgroud)

  • 那个 MiB,而不是 MB 等等...... (4认同)

Rom*_*cea 8

万一有人在寻找这个问题的反面(我确实这样做),这对我有用:

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
Run Code Online (Sandbox Code Playgroud)


Pet*_*r F 7

如果您已经知道所需的内容,请参见下文,以一种快速且相对易于阅读的方式在一行代码中打印文件大小。这些单行代码将上面@ccpizza的出色答案与一些方便的格式化技巧结合在一起,我在这里阅读了如何以千位分隔符的形式用逗号打印数字?

字节数

print ('{:,.0f}'.format(os.path.getsize(filepath))+" B")
Run Code Online (Sandbox Code Playgroud)

长袍

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<7))+" kb")
Run Code Online (Sandbox Code Playgroud)

千字节

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<10))+" KB")
Run Code Online (Sandbox Code Playgroud)

兆位

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<17))+" mb")
Run Code Online (Sandbox Code Playgroud)

兆字节

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<20))+" MB")
Run Code Online (Sandbox Code Playgroud)

千兆位

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<27))+" gb")
Run Code Online (Sandbox Code Playgroud)

千兆字节

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<30))+" GB")
Run Code Online (Sandbox Code Playgroud)

兆兆字节

print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<40))+" TB")
Run Code Online (Sandbox Code Playgroud)

显然,他们假设您一开始就大致知道要处理的大小,就我而言(西南伦敦电视台的视频编辑器),大小为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
>>> get_size("d:\\media\\bags of fun.avi")
'38 MB'
>>> get_size("d:\\media\\bags of fun.avi","KB")
'38,763 KB'
>>> get_size("d:\\media\\bags of fun.avi","kb")
'310,104 kb'
Run Code Online (Sandbox Code Playgroud)


kam*_*sar 7

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)
Run Code Online (Sandbox Code Playgroud)