293

バイトサイズから人間が読めるサイズを返す関数:

>>> human_readable(2048)
'2 kilobytes'
>>>

これを行う方法?

4

24 に答える 24

637

上記の「タスクが小さすぎてライブラリを必要としない」問題に対処するには、単純な実装 (f-strings を使用するため、Python 3.6+) を使用します。

def sizeof_fmt(num, suffix="B"):
    for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]:
        if abs(num) < 1024.0:
            return f"{num:3.1f}{unit}{suffix}"
        num /= 1024.0
    return f"{num:.1f}Yi{suffix}"

サポート:

  • 現在知られているすべてのバイナリプレフィックス
  • 負の数と正の数
  • 1000ヨビバイトより大きい数値
  • 任意の単位 (ギビビットで数えたいかもしれません!)

例:

>>> sizeof_fmt(168963795964)
'157.4GiB'

フレッド・シレラ

于 2009-07-07T21:15:41.397 に答える
151

あなたが探していると思われるすべての機能を備えたライブラリはですhumanizehumanize.naturalsize()あなたが探しているすべてをしているようです。

于 2013-03-18T19:29:28.413 に答える
38

これが私のバージョンです。forループは使用しません。一定の複雑さO(1)があり、理論的には、forループを使用するここでの回答よりも効率的です。

from math import log
unit_list = zip(['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2])
def sizeof_fmt(num):
    """Human friendly file size"""
    if num > 1:
        exponent = min(int(log(num, 1024)), len(unit_list) - 1)
        quotient = float(num) / 1024**exponent
        unit, num_decimals = unit_list[exponent]
        format_string = '{:.%sf} {}' % (num_decimals)
        return format_string.format(quotient, unit)
    if num == 0:
        return '0 bytes'
    if num == 1:
        return '1 byte'

何が起こっているのかをより明確にするために、文字列フォーマットのコードを省略できます。実際に作業を行う行は次のとおりです。

exponent = int(log(num, 1024))
quotient = num / 1024**exponent
unit_list[exponent]
于 2012-04-16T09:16:44.987 に答える
38

そういう人は必ずいるはずです。さて今日は私です。これは 1 行です。関数シグネチャを数えると 2 行になります。

def human_size(bytes, units=[' bytes','KB','MB','GB','TB', 'PB', 'EB']):
    """ Returns a human readable string representation of bytes """
    return str(bytes) + units[0] if bytes < 1024 else human_size(bytes>>10, units[1:])

 </p>

>>> human_size(123)
123 bytes
>>> human_size(123456789)
117GB

エクサバイトより大きいサイズが必要な場合は、もう少し危険です。

def human_size(bytes, units=[' bytes','KB','MB','GB','TB', 'PB', 'EB']):
    return str(bytes) + units[0] if bytes < 1024 else human_size(bytes>>10, units[1:]) if units[1:] else f'{bytes>>10}ZB'
于 2017-05-03T03:09:22.893 に答える
10

そのようなライブラリの 1 つに、rush.filesizeがあります。

>>> from hurry.filesize import alternative
>>> size(1, system=alternative)
'1 byte'
>>> size(10, system=alternative)
'10 bytes'
>>> size(1024, system=alternative)
'1 KB'
于 2009-07-07T21:00:25.717 に答える
8

1000 の累乗またはキビバイトのいずれかを使用すると、より標準に適しています。

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)

PS K(大文字)サフィックスで数千を印刷するライブラリを決して信頼しないでください:)

于 2014-05-21T02:49:09.130 に答える
6

これは、ほぼすべての状況で必要なことを実行し、オプションの引数でカスタマイズ可能であり、ご覧のとおり、ほぼ自己文書化されています。

from math import log
def pretty_size(n,pow=0,b=1024,u='B',pre=['']+[p+'i'for p in'KMGTPEZY']):
    pow,n=min(int(log(max(n*b**pow,1),b)),len(pre)-1),n*b**pow
    return "%%.%if %%s%%s"%abs(pow%(-pow-1))%(n/b**float(pow),pre[pow],u)

出力例:

>>> pretty_size(42)
'42 B'

>>> pretty_size(2015)
'2.0 KiB'

>>> pretty_size(987654321)
'941.9 MiB'

>>> pretty_size(9876543210)
'9.2 GiB'

>>> pretty_size(0.5,pow=1)
'512 B'

>>> pretty_size(0)
'0 B'

高度なカスタマイズ:

>>> pretty_size(987654321,b=1000,u='bytes',pre=['','kilo','mega','giga'])
'987.7 megabytes'

>>> pretty_size(9876543210,b=1000,u='bytes',pre=['','kilo','mega','giga'])
'9.9 gigabytes'

このコードは、Python 2 と Python 3 の両方と互換性があります。PEP8 への準拠は、読者の課題です。きれいなのは出力であることを忘れないでください。

アップデート:

何千ものコンマが必要な場合は、明白な拡張子を適用するだけです:

def prettier_size(n,pow=0,b=1024,u='B',pre=['']+[p+'i'for p in'KMGTPEZY']):
    r,f=min(int(log(max(n*b**pow,1),b)),len(pre)-1),'{:,.%if} %s%s'
    return (f%(abs(r%(-r-1)),pre[r],u)).format(n*b**pow/b**float(r))

例えば:

>>> pretty_units(987654321098765432109876543210)
'816,968.5 YiB'
于 2015-07-02T07:53:30.480 に答える
5

rush.filesize() の代替として提供されているスニペットをリフすると、使用する接頭辞に基づいてさまざまな精度の数値を与えるスニペットを次に示します。一部のスニペットほど簡潔ではありませんが、結果は気に入っています。

def human_size(size_bytes):
    """
    format a size in bytes into a 'human' file size, e.g. bytes, KB, MB, GB, TB, PB
    Note that bytes/KB will be reported in whole numbers but MB and above will have greater precision
    e.g. 1 byte, 43 bytes, 443 KB, 4.3 MB, 4.43 GB, etc
    """
    if size_bytes == 1:
        # because I really hate unnecessary plurals
        return "1 byte"

    suffixes_table = [('bytes',0),('KB',0),('MB',1),('GB',2),('TB',2), ('PB',2)]

    num = float(size_bytes)
    for suffix, precision in suffixes_table:
        if num < 1024.0:
            break
        num /= 1024.0

    if precision == 0:
        formatted_size = "%d" % num
    else:
        formatted_size = str(round(num, ndigits=precision))

    return "%s %s" % (formatted_size, suffix)
于 2011-07-01T11:40:16.303 に答える
4

以前のすべての回答から、これが私の見解です。ファイルサイズをバイト単位で整数として格納するオブジェクトです。しかし、オブジェクトを印刷しようとすると、人間が読めるバージョンが自動的に取得されます。

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)
于 2012-04-17T15:47:54.330 に答える
3

現代の Django には、自己テンプレート タグがありfilesizeformatます。

値をファイル サイズのようにフォーマットしhuman-readableます (つまり、「13 KB」、「4.1 MB」、「102 バイト」など)。

例えば:

{{ value|filesizeformat }}

値が 123456789 の場合、出力は 117.7 MB になります。

詳細: https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#filesizeformat

于 2017-02-18T15:53:04.233 に答える
2

私は sentleの 10 進バージョンの固定精度が好きなので、上記の Joctee の回答との一種のハイブリッドを次に示します (整数以外の基数でログを取得できることをご存知ですか?):

from math import log
def human_readable_bytes(x):
    # hybrid of https://stackoverflow.com/a/10171475/2595465
    #      with https://stackoverflow.com/a/5414105/2595465
    if x == 0: return '0'
    magnitude = int(log(abs(x),10.24))
    if magnitude > 16:
        format_str = '%iP'
        denominator_mag = 15
    else:
        float_fmt = '%2.1f' if magnitude % 3 == 1 else '%1.2f'
        illion = (magnitude + 1) // 3
        format_str = float_fmt + ['', 'K', 'M', 'G', 'T', 'P'][illion]
    return (format_str % (x * 1.0 / (1024 ** illion))).lstrip('0')
于 2013-07-19T19:36:16.870 に答える
0
def human_readable_data_quantity(quantity, multiple=1024):
    if quantity == 0:
        quantity = +0
    SUFFIXES = ["B"] + [i + {1000: "B", 1024: "iB"}[multiple] for i in "KMGTPEZY"]
    for suffix in SUFFIXES:
        if quantity < multiple or suffix == SUFFIXES[-1]:
            if suffix == SUFFIXES[0]:
                return "%d%s" % (quantity, suffix)
            else:
                return "%.1f%s" % (quantity, suffix)
        else:
            quantity /= multiple
于 2010-02-02T02:29:43.530 に答える
0

この機能は、ほとんどのプロジェクトで非常に便利なライブラリであるBoltonsで利用できる場合に使用できます。

>>> bytes2human(128991)
'126K'
>>> bytes2human(100001221)
'95M'
>>> bytes2human(0, 2)
'0.00B'
于 2020-10-21T20:15:51.647 に答える