Pustaka yang dapat digunakan kembali untuk mendapatkan versi ukuran file yang dapat dibaca manusia?

238

Ada berbagai cuplikan di web yang akan memberi Anda fungsi untuk mengembalikan ukuran yang dapat dibaca manusia dari ukuran byte:

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

Tetapi apakah ada perpustakaan Python yang menyediakan ini?

Sridhar Ratnakumar
sumber
2
Saya pikir ini jatuh di bawah judul "tugas terlalu kecil untuk memerlukan perpustakaan". Jika Anda melihat sumbernya untuk hurry.filesize, hanya ada satu fungsi, dengan selusin baris kode. Dan bahkan itu bisa dipadatkan.
Ben Blank
8
Keuntungan menggunakan pustaka adalah bahwa ia biasanya diuji (berisi tes yang dapat dijalankan jika ada pengeditan yang memperkenalkan bug). Jika Anda menambahkan tes, maka itu tidak lagi 'lusin baris kode' :-)
Sridhar Ratnakumar
Jumlah menciptakan kembali roda di komunitas python gila dan konyol. Hanya ls -h /path/to/file.ext akan melakukan pekerjaan. Karena itu, jawaban yang diterima adalah melakukan pekerjaan dengan baik. Kudo.
Edward Aung

Jawaban:

523

Mengatasi masalah "tugas yang terlalu kecil untuk memerlukan pustaka" di atas dengan implementasi langsung:

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

Mendukung:

  • semua awalan biner yang saat ini dikenal
  • angka negatif dan positif
  • angka lebih besar dari 1000 Yobibytes
  • unit sewenang-wenang (mungkin Anda suka menghitung dalam Gibibit!)

Contoh:

>>> sizeof_fmt(168963795964)
'157.4GiB'

oleh Fred Cirera

Sridhar Ratnakumar
sumber
4
Harus ada ruang antara angka dan unit. Jika Anda menghasilkan html atau lateks, itu harus berupa ruang non-pemecahan.
josch
3
hanya pemikiran, tetapi untuk sufiks (?) selain dari B(yaitu untuk unit selain byte) Anda ingin faktor menjadi 1000.0daripada 1024.0bukan?
Anentropic
5
Jika Anda ingin meningkatkan ketelitian komponen desimal, ubah 1garis on 4 dan 6 ke ketepatan yang Anda inginkan.
Matius G
44
tentu akan lebih baik jika semua iterasi ini pada "tugas yang terlalu kecil" ditangkap dan dienkapsulasi ke perpustakaan dengan tes.
fess.
6
@ MD004 Sebaliknya. Awalan didefinisikan sedemikian rupa sehingga 1 KB = 1000 B dan 1 KiB = 1024 B.
augurar
116

Perpustakaan yang memiliki semua fungsi yang tampaknya Anda cari adalah humanize. humanize.naturalsize()tampaknya melakukan semua yang Anda cari.

Pyrocater
sumber
9
Beberapa contoh menggunakan data dari OP: humanize.naturalsize(2048) # => '2.0 kB' ,humanize.naturalsize(2048, binary=True) # => '2.0 KiB' humanize.naturalsize(2048, gnu=True) # => '2.0K'
RubenLaguna
33

Ini versiku. Itu tidak menggunakan for-loop. Ini memiliki kompleksitas konstan, O ( 1 ), dan secara teori lebih efisien daripada jawaban di sini yang menggunakan for-loop.

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'

Untuk membuatnya lebih jelas apa yang sedang terjadi, kita dapat menghilangkan kode untuk pemformatan string. Berikut adalah baris yang benar-benar melakukan pekerjaan:

exponent = int(log(num, 1024))
quotient = num / 1024**exponent
unit_list[exponent]
Joctee
sumber
2
saat Anda berbicara tentang mengoptimalkan kode pendek seperti itu, mengapa tidak menggunakan if / elif / else? Pemeriksaan terakhir num == 1 tidak perlu kecuali Anda mengharapkan ukuran file negatif. Kalau tidak: kerja bagus, saya suka versi ini.
ted
2
Kode saya pasti bisa lebih dioptimalkan. Namun, maksud saya adalah untuk menunjukkan bahwa tugas ini dapat diselesaikan dengan kompleksitas yang konstan.
joctee
37
Jawaban dengan for loop juga O (1), karena for loop dibatasi - waktu perhitungannya tidak berskala dengan ukuran input (kami tidak memiliki awalan SI yang tidak terikat).
Thomas Minor
1
mungkin harus menambahkan koma untuk pemformatan, jadi 1000akan ditampilkan sebagai 1,000 bytes.
iTayb
3
Perhatikan bahwa saat menggunakan Python 3, zip mengembalikan iterator, jadi Anda perlu membungkusnya dengan list (). unit_list = list(zip(['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2]))
donarb
30

Karya-karya berikut di Python 3.6+, adalah, menurut pendapat saya, jawaban termudah untuk dipahami di sini, dan memungkinkan Anda menyesuaikan jumlah tempat desimal yang digunakan.

def human_readable_size(size, decimal_places=3):
    for unit in ['B','KiB','MiB','GiB','TiB']:
        if size < 1024.0:
            break
        size /= 1024.0
    return f"{size:.{decimal_places}f}{unit}"
wp-overwatch.com
sumber
26

Meskipun saya tahu pertanyaan ini kuno, saya baru-baru ini membuat versi yang menghindari loop, gunakan log2untuk menentukan urutan ukuran yang berfungsi ganda sebagai pergeseran dan indeks ke dalam daftar akhiran:

from math import log2

_suffixes = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']

def file_size(size):
    # determine binary order in steps of size 10 
    # (coerce to int, // still returns a float)
    order = int(log2(size) / 10) if size else 0
    # format file size
    # (.4g results in rounded numbers for exact matches and max 3 decimals, 
    # should never resort to exponent values)
    return '{:.4g} {}'.format(size / (1 << (order * 10)), _suffixes[order])

Bisa juga dianggap unpythonic karena mudah dibaca, :)

aliasIDIOT
sumber
1
Sementara saya suka hal log2, Anda harus menangani ukuran == 0!
Marti Nito
Anda perlu membungkus salah satu sizeatau (1 << (order * 10)di float()dalam baris terakhir (untuk python 2).
Harvey
FYI: beberapa mungkin perlu import mathdi sana.
monsto
@monsto true, ditambahkan :)
akaIDIOT
Senang betapa kompaknya ini! Terima kasih sudah berbagi.
John Crawford
17

Pasti selalu ada salah satu dari mereka. Baiklah hari ini saya. Inilah solusi satu-liner - atau dua baris jika Anda menghitung tanda tangan fungsi.

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

>>> human_size(123)
123 bytes
>>> human_size(123456789)
117GB
wp-overwatch.com
sumber
1
FYI, output akan selalu dibulatkan ke bawah.
wp-overwatch.com
1
bukankah lebih baik untuk menetapkan daftar default untuk unit di dalam metode untuk menghindari menggunakan daftar sebagai argumen default? (dan units=Nonesebagai gantinya menggunakan )
Imanol
3
@ImanolEizaguirre Praktik terbaik akan menyatakan bahwa itu ide yang baik untuk dilakukan seperti yang Anda sarankan, jadi Anda tidak secara tidak sengaja memperkenalkan bug ke dalam suatu program. Namun, fungsi ini seperti yang ditulis aman karena daftar unit tidak pernah dimanipulasi. Jika itu dimanipulasi, perubahan akan permanen, dan setiap panggilan fungsi berikutnya akan menerima versi daftar yang dimanipulasi sebagai argumen default untuk argumen unit.
wp-overwatch.com
Untuk Python 3, jika Anda ingin titik desimal, gunakan ini sebagai gantinya: `` `def human_size (fsize, units = ['bytes', 'KB', 'MB', 'GB', 'GB', 'TB', 'PB', 'EB']): return "{: .2f} {}". Format (float (fsize), units [0]) jika fsize <1024 lain human_size (fsize / 1024, units [1:]) `` `
Omer
15

Jika Anda menggunakan Django terinstal, Anda juga dapat mencoba format filesize :

from django.template.defaultfilters import filesizeformat
filesizeformat(1073741824)

=>

"1.0 GB"
Jon Tirsen
sumber
1
Satu kelemahan untuk ini bagi saya adalah bahwa ia menggunakan GB bukan GiB meskipun itu membagi dengan 1024.
Pepedou
9

Salah satu perpustakaan semacam itu adalah 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'
Sridhar Ratnakumar
sumber
3
Namun, perpustakaan ini tidak dapat dikustomisasi. >>> dari hurry.filesize ukuran impor >>> ukuran (1031053) >>> ukuran (3033053) '2M' Saya berharap ini menunjukkan, misalnya, '2.4M' atau '2423K' .. alih-alih secara terang-terangan didekati ' 2 jt.
Sridhar Ratnakumar
Perhatikan juga bahwa sangat mudah untuk hanya mengambil kode dari rush.filesize dan memasukkannya langsung ke dalam kode Anda sendiri, jika Anda berurusan dengan sistem ketergantungan dan sejenisnya. Ini sependek potongan yang diberikan orang di sini.
mlissner
@SridharRatnakumar, untuk mengatasi masalah perkiraan terlalu banyak, silakan lihat retas matematis saya . Bisakah pendekatan ini ditingkatkan lebih lanjut?
Acumenus
9

Menggunakan kekuatan 1000 atau kibibytes akan lebih ramah-standar:

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 Jangan pernah percaya perpustakaan yang mencetak ribuan dengan akhiran K (huruf besar) :)

Giancarlo Sportelli
sumber
P.S. Never trust a library that prints thousands with the K (uppercase) suffix :)Kenapa tidak? Kode dapat terdengar sempurna dan penulis tidak mempertimbangkan casing untuk kilo. Tampaknya cukup bodoh untuk secara otomatis mengabaikan kode apa pun berdasarkan aturan Anda ...
Douglas Gaskell
7

Ini akan melakukan apa yang Anda butuhkan di hampir semua situasi, dapat disesuaikan dengan argumen opsional, dan seperti yang Anda lihat, cukup banyak mendokumentasikan diri:

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)

Contoh output:

>>> 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'

Kustomisasi lanjutan:

>>> 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'

Kode ini kompatibel dengan Python 2 dan Python 3. Kepatuhan PEP8 adalah latihan untuk pembaca. Ingat, outputnya cantik.

Memperbarui:

Jika Anda membutuhkan ribuan koma, cukup terapkan ekstensi yang jelas:

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))

Sebagai contoh:

>>> pretty_units(987654321098765432109876543210)
'816,968.5 YiB'
gojomo
sumber
7

Anda harus menggunakan "memanusiakan".

>>> humanize.naturalsize(1000000)
'1.0 MB'
>>> humanize.naturalsize(1000000, binary=True)
'976.6 KiB'
>>> humanize.naturalsize(1000000, gnu=True)
'976.6K'

Referensi:

https://pypi.org/project/humanize/

Saeed Zahedian Abroodi
sumber
6

Riffing pada snippet yang disediakan sebagai alternatif untuk terburu-buru.filesize (), di sini adalah snippet yang memberikan angka presisi yang bervariasi berdasarkan awalan yang digunakan. Tidak sesempit beberapa cuplikan, tapi saya suka hasilnya.

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)
markltbaker
sumber
6

Proyek HumanFriendly membantu dalam hal ini .

import humanfriendly
humanfriendly.format_size(1024)

Kode di atas akan memberikan 1KB sebagai jawaban.
Contohnya dapat ditemukan di sini .

arumuga abinesh
sumber
4

Menarik dari semua jawaban sebelumnya, inilah pendapat saya. Ini adalah objek yang akan menyimpan ukuran file dalam byte sebagai integer. Tetapi ketika Anda mencoba untuk mencetak objek, Anda secara otomatis mendapatkan versi yang dapat dibaca manusia.

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)
xApple
sumber
3

Saya suka ketepatan tetap dari versi desimal pengirim , jadi inilah semacam hibrida dari itu dengan jawaban joctee di atas (apakah Anda tahu Anda dapat mengambil log dengan basis non-integer?):

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')
HST
sumber
2

DiveIntoPython3 juga berbicara tentang fungsi ini.

Sridhar Ratnakumar
sumber
2

Bagaimana dengan 2 liner sederhana:

def humanizeFileSize(filesize):
    p = int(math.floor(math.log(filesize, 2)/10))
    return "%.3f%s" % (filesize/math.pow(1024,p), ['B','KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'][p])

Inilah cara kerjanya di bawah tenda:

  1. Menghitung log 2 (filesize)
  2. Membagi dengan 10 untuk mendapatkan unit terdekat. (mis. jika ukurannya 5.000 byte, unit terdekat adalah Kb, jadi jawabannya harus X KiB)
  3. Kembali file_size/value_of_closest_unitbersama dengan unit.

Namun itu tidak berfungsi jika ukuran file adalah 0 atau negatif (karena log tidak terdefinisi untuk angka 0 dan -ve). Anda dapat menambahkan cek tambahan untuk mereka:

def humanizeFileSize(filesize):
    filesize = abs(filesize)
    if (filesize==0):
        return "0 Bytes"
    p = int(math.floor(math.log(filesize, 2)/10))
    return "%0.2f %s" % (filesize/math.pow(1024,p), ['Bytes','KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'][p])

Contoh:

>>> humanizeFileSize(538244835492574234)
'478.06 PiB'
>>> humanizeFileSize(-924372537)
'881.55 MiB'
>>> humanizeFileSize(0)
'0 Bytes'

CATATAN - Ada perbedaan antara Kb dan KiB. KB berarti 1000 byte, sedangkan KiB berarti 1024 byte. KB, MB, GB semuanya kelipatan 1000, sedangkan KiB, MiB, GiB dll semua kelipatan 1024. Lebih lanjut tentang hal ini di sini

jerigen
sumber
1
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
Matt Joiner
sumber
1

Apa yang akan Anda temukan di bawah ini bukanlah solusi yang paling berkinerja atau terpendek di antara yang sudah diposting. Alih-alih, ini berfokus pada satu masalah tertentu yang tidak dijawab oleh banyak jawaban lainnya.

Yaitu kasus ketika input suka 999_995diberikan:

Python 3.6.1 ...
...
>>> value = 999_995
>>> base = 1000
>>> math.log(value, base)
1.999999276174054

yang, terpotong ke bilangan bulat terdekat dan diterapkan kembali ke input yang diberikan

>>> order = int(math.log(value, base))
>>> value/base**order
999.995

Ini tampaknya persis seperti yang kita harapkan sampai kita diharuskan mengendalikan presisi keluaran . Dan saat inilah segalanya mulai menjadi sedikit sulit.

Dengan presisi yang diatur ke 2 digit, kita dapat:

>>> round(value/base**order, 2)
1000 # K

bukannya 1M.

Bagaimana kita bisa mengatasinya?

Tentu saja, kita dapat memeriksanya secara eksplisit:

if round(value/base**order, 2) == base:
    order += 1

Tetapi bisakah kita melakukan yang lebih baik? Bisakah kita mengetahui jalan mana yang orderharus dipotong sebelum kita melakukan langkah terakhir?

Ternyata kita bisa.

Dengan asumsi 0,5 aturan pembulatan desimal, ifkondisi di atas diterjemahkan menjadi:

masukkan deskripsi gambar di sini

yang menghasilkan

def abbreviate(value, base=1000, precision=2, suffixes=None):
    if suffixes is None:
        suffixes = ['', 'K', 'M', 'B', 'T']

    if value == 0:
        return f'{0}{suffixes[0]}'

    order_max = len(suffixes) - 1
    order = log(abs(value), base)
    order_corr = order - int(order) >= log(base - 0.5/10**precision, base)
    order = min(int(order) + order_corr, order_max)

    factored = round(value/base**order, precision)

    return f'{factored:,g}{suffixes[order]}'

memberi

>>> abbreviate(999_994)
'999.99K'
>>> abbreviate(999_995)
'1M'
>>> abbreviate(999_995, precision=3)
'999.995K'
>>> abbreviate(2042, base=1024)
'1.99K'
>>> abbreviate(2043, base=1024)
'2K'
ayorgo
sumber
0

rujuk Sridhar Ratnakumarjawaban, diperbarui ke:

def formatSize(sizeInBytes, decimalNum=1, isUnitWithI=False, sizeUnitSeperator=""):
  """format size to human readable string"""
  # https://en.wikipedia.org/wiki/Binary_prefix#Specific_units_of_IEC_60027-2_A.2_and_ISO.2FIEC_80000
  # K=kilo, M=mega, G=giga, T=tera, P=peta, E=exa, Z=zetta, Y=yotta
  sizeUnitList = ['','K','M','G','T','P','E','Z']
  largestUnit = 'Y'

  if isUnitWithI:
    sizeUnitListWithI = []
    for curIdx, eachUnit in enumerate(sizeUnitList):
      unitWithI = eachUnit
      if curIdx >= 1:
        unitWithI += 'i'
      sizeUnitListWithI.append(unitWithI)

    # sizeUnitListWithI = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']
    sizeUnitList = sizeUnitListWithI

    largestUnit += 'i'

  suffix = "B"
  decimalFormat = "." + str(decimalNum) + "f" # ".1f"
  finalFormat = "%" + decimalFormat + sizeUnitSeperator + "%s%s" # "%.1f%s%s"
  sizeNum = sizeInBytes
  for sizeUnit in sizeUnitList:
      if abs(sizeNum) < 1024.0:
        return finalFormat % (sizeNum, sizeUnit, suffix)
      sizeNum /= 1024.0
  return finalFormat % (sizeNum, largestUnit, suffix)

dan contoh outputnya adalah:

def testKb():
  kbSize = 3746
  kbStr = formatSize(kbSize)
  print("%s -> %s" % (kbSize, kbStr))

def testI():
  iSize = 87533
  iStr = formatSize(iSize, isUnitWithI=True)
  print("%s -> %s" % (iSize, iStr))

def testSeparator():
  seperatorSize = 98654
  seperatorStr = formatSize(seperatorSize, sizeUnitSeperator=" ")
  print("%s -> %s" % (seperatorSize, seperatorStr))

def testBytes():
  bytesSize = 352
  bytesStr = formatSize(bytesSize)
  print("%s -> %s" % (bytesSize, bytesStr))

def testMb():
  mbSize = 76383285
  mbStr = formatSize(mbSize, decimalNum=2)
  print("%s -> %s" % (mbSize, mbStr))

def testTb():
  tbSize = 763832854988542
  tbStr = formatSize(tbSize, decimalNum=2)
  print("%s -> %s" % (tbSize, tbStr))

def testPb():
  pbSize = 763832854988542665
  pbStr = formatSize(pbSize, decimalNum=4)
  print("%s -> %s" % (pbSize, pbStr))


def demoFormatSize():
  testKb()
  testI()
  testSeparator()
  testBytes()
  testMb()
  testTb()
  testPb()

  # 3746 -> 3.7KB
  # 87533 -> 85.5KiB
  # 98654 -> 96.3 KB
  # 352 -> 352.0B
  # 76383285 -> 72.84MB
  # 763832854988542 -> 694.70TB
  # 763832854988542665 -> 678.4199PB
crifan
sumber
0

Solusi ini mungkin juga menarik bagi Anda, tergantung pada bagaimana pikiran Anda bekerja:

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'
Peter F
sumber