【问题标题】:Python libraries to calculate human readable filesize from bytes?Python库从字节计算人类可读文件大小?
【发布时间】:2013-02-06 10:25:18
【问题描述】:

我发现hurry.filesize 非常有用,但它不提供十进制输出?

例如:

print size(4026, system=alternative) gives 3 KB.

但后来当我添加所有值时,我没有得到确切的总和。例如,如果hurry.filesize 的输出在 4 个变量中,每个值为 3。如果我将它们全部相加,我得到的输出为 15。

我正在寻找 hurry.filesize 的替代方法来获得小数输出。

【问题讨论】:

  • 你试过os.path.getsize()吗?

标签: python python-module


【解决方案1】:

每次我写一个小脚本或 ipynb 或其他什么时,我都会重新发明轮子。它很老套,所以我写了datasize python 模块。我在这里发布这个是因为我刚刚更新了它,哇,Python 版本已经升级了!

它是一个 DataSize 类,它是 int 的子类,所以算术可以正常工作,但是它会从算术返回 int,因为我将它与 Pandas 和一些 numpy 一起使用,并且我不想在有 python 时放慢速度 矩阵数学库的 C++ 翻译。

您可以使用带有位或字节的 SI 或 NIST 后缀的字符串来构造 DataSize 对象,如果您需要为使用这些数据的嵌入式技术处理数据,甚至可以使用奇怪的字长。 DataSize 对象具有直观的 format() 代码语法,用于人类可读的表示。在内部,该值只是 8 位字节的整数计数。

例如。

>>> from datasize import DataSize
>>> 'My new {:GB} SSD really only stores {:.2GiB} of data.'.format(DataSize('750GB'),DataSize(DataSize('750GB') * 0.8))
'My new 750GB SSD really only stores 558.79GiB of data.'

【讨论】:

    【解决方案2】:

    这并不难自己实现:

    suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
    def humansize(nbytes):
        i = 0
        while nbytes >= 1024 and i < len(suffixes)-1:
            nbytes /= 1024.
            i += 1
        f = ('%.2f' % nbytes).rstrip('0').rstrip('.')
        return '%s %s' % (f, suffixes[i])
    

    例子:

    >>> humansize(131)
    '131 B'
    >>> humansize(1049)
    '1.02 KB'
    >>> humansize(58812)
    '57.43 KB'
    >>> humansize(68819826)
    '65.63 MB'
    >>> humansize(39756861649)
    '37.03 GB'
    >>> humansize(18754875155724)
    '17.06 TB'
    

    【讨论】:

    • 就是这样,但问题是:如果输出为 4.12,则为 4.12,但如果输出为 4,则为 4.00。我只想要 4 没有小数。
    • 添加了round,这样您就只能得到两位小数。
    • 有点迂腐,但你可能想使用 KiB、MiB 等......
    • 我碰巧非常不喜欢这些后缀。但是,由于代码非常清晰,如果你真的想要改变它应该不难;)
    【解决方案3】:

    这并不需要比@nneonneo 解决方案更快,它只是有点更酷,如果我可以这么说的话:)

    import math
    
    suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
    
    def human_size(nbytes):
      human = nbytes
      rank = 0
      if nbytes != 0:
        rank = int((math.log10(nbytes)) / 3)
        rank = min(rank, len(suffixes) - 1)
        human = nbytes / (1024.0 ** rank)
      f = ('%.2f' % human).rstrip('0').rstrip('.')
      return '%s %s' % (f, suffixes[rank])
    

    这是基于这样一个事实,即任何以 10 为底的对数的整数部分比实际位数少一。其余的几乎都是直截了当的。

    【讨论】:

    • 您将排名作为 base-1000 日志而不是 base-1024 日志。为什么不改用math.log(nbytes, 1024)?这样做更明显。
    • 如果 nbytes == 0,math.log10 调用失败并显示“ValueError: math domain error”。您需要额外检查:if nbytes == 0: return "0 B"
    【解决方案4】:

    免责声明:我写了我要描述的包

    模块bitmath 支持您描述的功能。它还解决了@filmore 的评论,即语义上我们应该使用 NIST 单位前缀(而不是 SI),也就是说,MiB 而不是 MB。现在也支持四舍五入

    您最初询问的是:

    print size(4026, system=alternative)
    

    bitmath 中,默认前缀单位系统是 NIST(基于 1024),因此,假设您指的是 4026 bytesbitmath 中的等效解决方案 看起来像以下任何一种:

    In [1]: import bitmath
    
    In [2]: print bitmath.Byte(bytes=4026).best_prefix()
    3.931640625KiB
    
    In [3]: human_prefix = bitmath.Byte(bytes=4026).best_prefix()
    
    In [4]: print human_prefix.format("{value:.2f} {unit}")
    3.93 KiB
    

    我目前有一个open task,允许用户在使用best_prefix 方法时选择首选的前缀单位系统。

    更新:2014-07-16 最新的软件包上传到PyPi,它包含几个新功能(完整功能列表在the GitHub page )

    【讨论】:

    • 我了解一些开发人员认为这是一个“需要库的任务太小”,但我不同意,因为这会导致开发人员不断重新发明轮子。无论如何,这个图书馆正是我想要的!谢谢蒂姆!
    • 这不是重新发明轮子,只是学习它:) 用于此类事情的软件包是无稽之谈。一个 sn-p 就足够了。只包含方法的包正在污染存储库和依赖项。这是一种太多人会因为懒惰而使用的包,有一天作者决定改变一些东西......
    • @RomainVincent 拥有相同的代码副本并粘贴在可能的数千个项目中,这就是我所说的污染。尤其是如果后来碰巧发现了导致错误的极端情况,那么修复该代码的每个实例都是一场噩梦。例如,accepted answer by nneonneo 中的代码在最初发布 4 年后得到了改进。在这种情况下,这不是一个很大的变化,但它说明了这一点。不是每个过去复制它的人都可能注意到甚至进行了更改。
    • 嗯,是的。但前提是你一开始不明白你在做什么。这就是为什么在这样简单直接的事情上可能存在错误的原因。这是一个数学公式,它不是通过复杂协议进行通信,也不是处理 ... 库的代码。你所说的免费修复错误的可能性,我称之为有人在你自己的代码中引入意外更改的危险。
    猜你喜欢
    • 1970-01-01
    • 2017-08-09
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多