Thư viện tái sử dụng để có được phiên bản kích thước tập tin con người có thể đọc được?


238

Có nhiều đoạn mã khác nhau trên web sẽ cung cấp cho bạn một hàm để trả về kích thước có thể đọc được của con người từ kích thước byte:

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

Nhưng có một thư viện Python cung cấp cái này không?


2
Tôi nghĩ rằng điều này nằm trong tiêu đề "một nhiệm vụ quá nhỏ để yêu cầu một thư viện". Nếu bạn nhìn vào nguồn cho rush.filesize, chỉ có một hàm duy nhất, với hàng tá dòng mã. Và thậm chí có thể được nén.
Ben Trống

8
Ưu điểm của việc sử dụng thư viện là nó thường được kiểm tra (chứa các kiểm tra có thể chạy trong trường hợp nếu chỉnh sửa của một người giới thiệu một lỗi). Nếu bạn thêm các bài kiểm tra, thì đó không còn là 'hàng chục dòng mã' :-)
Sridhar Ratnakumar

Số lượng phát minh lại bánh xe trong cộng đồng python là điên rồ và lố bịch. Chỉ cần ls -h /path/to/file.ext sẽ thực hiện công việc. Có nói rằng, câu trả lời được chấp nhận là làm một công việc tốt. Kudo.
Edward Aung

Câu trả lời:


522

Giải quyết vấn đề "quá nhỏ để yêu cầu thư viện" ở trên bằng cách thực hiện đơn giản:

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)

Hỗ trợ:

  • tất cả các tiền tố nhị phân hiện được biết đến
  • số âm và dương
  • số lượng lớn hơn 1000 Yobibytes
  • các đơn vị tùy ý (có thể bạn muốn tính bằng Gibibits!)

Thí dụ:

>>> sizeof_fmt(168963795964)
'157.4GiB'

bởi Fred Cirera


4
Cần có một khoảng cách giữa số và đơn vị. Nếu bạn xuất ra html hoặc latex, nó sẽ là một không gian không phá vỡ.
josch

3
chỉ là một ý nghĩ, nhưng đối với bất kỳ hậu tố (?) nào khác ngoài B(ví dụ: đối với các đơn vị không phải là byte), bạn muốn yếu tố này 1000.0chứ không phải là 1024.0không?
Anentropic

5
Nếu bạn muốn tăng độ chính xác của thành phần thập phân, hãy thay đổi 1dòng 4 và 6 thành bất kỳ độ chính xác nào bạn muốn.
Matthew G

44
chắc chắn sẽ rất tuyệt nếu tất cả các lần lặp này trong "nhiệm vụ quá nhỏ" này được ghi lại và gói gọn trong một thư viện với các bài kiểm tra.
fess.

6
@ MD004 Đó là cách khác. Các tiền tố được xác định sao cho 1 KB = 1000 B và 1 KiB = 1024 B.
augurar

116

Một thư viện có tất cả các chức năng mà dường như bạn đang tìm kiếm humanize. humanize.naturalsize()dường như làm mọi thứ bạn đang tìm kiếm.


9
Một số ví dụ sử dụng dữ liệu từ OP : humanize.naturalsize(2048) # => '2.0 kB' ,humanize.naturalsize(2048, binary=True) # => '2.0 KiB' humanize.naturalsize(2048, gnu=True) # => '2.0K'
RubenLaguna

32

Đây là phiên bản của tôi. Nó không sử dụng vòng lặp for. Nó có độ phức tạp không đổi, O ( 1 ) và về mặt lý thuyết hiệu quả hơn các câu trả lời ở đây sử dụng vòng lặp 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'

Để làm rõ hơn những gì đang diễn ra, chúng ta có thể bỏ qua mã cho định dạng chuỗi. Dưới đây là các dòng thực sự làm việc:

exponent = int(log(num, 1024))
quotient = num / 1024**exponent
unit_list[exponent]

2
Trong khi bạn nói về việc tối ưu hóa một mã ngắn như vậy, tại sao không sử dụng if / elif / other? Kiểm tra cuối num == 1 là không cần thiết trừ khi bạn mong đợi kích thước tệp âm. Nếu không: công việc tốt, tôi thích phiên bản này.
ted

2
Mã của tôi chắc chắn có thể được tối ưu hóa hơn. Tuy nhiên, quan điểm của tôi là chứng minh rằng nhiệm vụ này có thể được giải quyết với độ phức tạp không đổi.
joctee

37
Các câu trả lời cho các vòng lặp cũng là O (1), vì các vòng lặp for bị giới hạn - thời gian tính toán của chúng không theo tỷ lệ với kích thước của đầu vào (chúng tôi không có tiền tố SI không giới hạn).
Thomas nhỏ

1
có lẽ nên thêm dấu phẩy cho định dạng, vì vậy 1000sẽ hiển thị dưới dạng 1,000 bytes.
iTayb

3
Lưu ý rằng khi sử dụng Python 3, zip trả về một trình vòng lặp, do đó bạn cần phải bọc nó bằng list (). unit_list = list(zip(['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2]))
donarb

30

Theo tôi, các công việc sau đây trong Python 3.6+ là câu trả lời dễ hiểu nhất ở đây và cho phép bạn tùy chỉnh số lượng vị trí thập phân được sử dụng.

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}"

26

Trong khi tôi biết câu hỏi này là cổ xưa, gần đây tôi đã đưa ra một phiên bản tránh các vòng lặp, sử dụng log2để xác định thứ tự kích thước tăng gấp đôi khi thay đổi và một chỉ mục vào danh sách hậu tố:

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

Mặc dù cũng có thể được coi là unpythonic cho khả năng đọc của nó :)


1
Trong khi tôi thích điều log2, bạn nên xử lý kích thước == 0!
Marti Nito

Bạn cần phải bọc sizehoặc (1 << (order * 10)trong float()dòng cuối cùng (đối với python 2).
Harvey

FYI: một số có thể cần import mathlên đó.
monsto

@monsto đúng, đã thêm :)
akaIDIOT 23/215

Tình yêu này nhỏ gọn làm sao! Cảm ơn bạn đã chia sẻ.
John Crawford

17

Luôn luôn có một trong những kẻ đó. Chà, hôm nay là tôi. Đây là giải pháp một lớp lót - hoặc hai dòng nếu bạn đếm chữ ký hàm.

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

1
FYI, đầu ra sẽ luôn được làm tròn xuống.
wp-overwatch.com

1
Sẽ tốt hơn nếu chỉ định danh sách mặc định cho các đơn vị bên trong phương thức để tránh sử dụng danh sách làm đối số mặc định? (và sử dụng units=Nonethay thế)
Imanol

3
@ImanolEizaguirre Thực tiễn tốt nhất sẽ nói rằng đó là một ý tưởng tốt để làm như bạn đề xuất, vì vậy bạn không vô tình đưa lỗi vào một chương trình. Tuy nhiên, chức năng này vì nó được viết là an toàn vì danh sách các đơn vị không bao giờ bị thao túng. Nếu nó bị thao túng, các thay đổi sẽ là vĩnh viễn và mọi lệnh gọi hàm tiếp theo sẽ nhận được một phiên bản danh sách bị thao túng làm đối số mặc định cho đối số đơn vị.
wp-overwatch.com

Đối với Python 3, nếu bạn muốn có dấu thập phân, thay vào đó, hãy sử dụng dấu này: `` `def human_size (fsize, units = ['byte', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']): return "{: .2f} {}". Format (float (fsize), đơn vị [0]) nếu fsize <1024 khác human_size (fsize / 1024, units [1:]) ``
Omer

15

Nếu bạn đang sử dụng Django, bạn cũng có thể thử filesizeformat :

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

=>

"1.0 GB"

1
Một nhược điểm đối với tôi là nó sử dụng GB thay vì GiB mặc dù nó chia cho 1024.
Pepedou

9

Một thư viện như vậy là 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'

3
Tuy nhiên, thư viện này không phải là rất tùy biến. >>> từ rush.filesize kích thước nhập khẩu >>> kích thước (1031053) >>> kích thước (3033053) '2M' Tôi mong đợi nó hiển thị, ví dụ: '2.4M' hoặc '2423K' .. thay vì xấp xỉ một cách trắng trợn ' 2 triệu '.
Sridhar Ratnakumar

Cũng lưu ý rằng thật dễ dàng để lấy mã ra một cách vội vàng. Định cỡ và đặt mã trực tiếp vào mã của riêng bạn, nếu bạn đang xử lý các hệ thống phụ thuộc và tương tự. Nó ngắn như những đoạn mà mọi người đang cung cấp ở đây.
mlissner

@SridharRatnakumar, để giải quyết vấn đề gần đúng một cách thông minh, xin vui lòng xem hack toán học của tôi . Cách tiếp cận có thể được cải thiện hơn nữa?
Acumenus

9

Sử dụng sức mạnh của 1000 hoặc kibibytes sẽ thân thiện với tiêu chuẩn hơn:

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 Không bao giờ tin tưởng một thư viện in hàng ngàn với hậu tố K (chữ hoa) :)


P.S. Never trust a library that prints thousands with the K (uppercase) suffix :)Tại sao không? Mã có thể là âm thanh hoàn hảo và tác giả chỉ không xem xét vỏ cho kilo. Có vẻ như việc tự động loại bỏ bất kỳ mã nào dựa trên quy tắc của bạn ...
Douglas Gaskell

7

Điều này sẽ làm những gì bạn cần trong hầu hết mọi tình huống, có thể tùy chỉnh với các đối số tùy chọn và như bạn có thể thấy, là khá nhiều tài liệu tự ghi:

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)

Ví dụ đầu ra:

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

Các tùy chỉnh nâng cao:

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

Mã này tương thích với cả Python 2 và Python 3. Tuân thủ PEP8 là một bài tập cho người đọc. Hãy nhớ rằng, đó là đầu ra đẹp.

Cập nhật:

Nếu bạn cần hàng nghìn dấu phẩy, chỉ cần áp dụng tiện ích mở rộng rõ ràng:

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

Ví dụ:

>>> pretty_units(987654321098765432109876543210)
'816,968.5 YiB'


6

Riffing trên đoạn trích được cung cấp thay thế cho rush.filesize (), đây là đoạn trích cung cấp các số chính xác khác nhau dựa trên tiền tố được sử dụng. Nó không phải là ngắn gọn như một số đoạn, nhưng tôi thích kết quả.

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)


4

Rút ra từ tất cả các câu trả lời trước đây, đây là của tôi về nó. Đó là một đối tượng sẽ lưu trữ kích thước tệp theo byte dưới dạng một số nguyên. Nhưng khi bạn cố gắng in đối tượng, bạn sẽ tự động có được một phiên bản có thể đọc được của con người.

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)

3

Tôi thích độ chính xác cố định của phiên bản thập phân của người gửi , vì vậy đây là một loại kết hợp với câu trả lời của joctee ở trên (bạn có biết bạn có thể lấy nhật ký với các cơ sở không nguyên không?):

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



2

Làm thế nào về một 2 lót đơn giản:

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

Đây là cách nó hoạt động dưới mui xe:

  1. Tính toán log 2 (kích thước tệp)
  2. Chia nó cho 10 để có được đơn vị gần nhất. (ví dụ: nếu kích thước là 5000 byte, đơn vị gần nhất là Kb, vì vậy câu trả lời phải là X KiB)
  3. Trả về file_size/value_of_closest_unitcùng với đơn vị.

Tuy nhiên, nó không hoạt động nếu kích thước tệp là 0 hoặc âm (vì nhật ký không được xác định cho các số 0 và -ve). Bạn có thể thêm kiểm tra thêm cho họ:

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

Ví dụ:

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

LƯU Ý - Có sự khác biệt giữa Kb và KiB. KB có nghĩa là 1000 byte, trong khi KiB có nghĩa là 1024 byte. KB, MB, GB đều là bội số của 1000, trong khi KiB, MiB, GiB, v.v ... đều là bội số của 1024. Thông tin thêm về nó ở đây


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

1

Những gì bạn sắp tìm thấy dưới đây không phải là giải pháp ngắn gọn hay hiệu quả nhất trong số những giải pháp đã được đăng. Thay vào đó, nó tập trung vào một vấn đề cụ thể mà nhiều câu trả lời khác bỏ lỡ.

Cụ thể là trường hợp khi đầu vào like 999_995được đưa ra:

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

trong đó, bị cắt cụt đến số nguyên gần nhất và được áp dụng trở lại đầu vào cho

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

Đây dường như là chính xác những gì chúng ta mong đợi cho đến khi chúng tôi được yêu cầu kiểm soát độ chính xác đầu ra . Và đây là khi mọi thứ bắt đầu hơi khó khăn.

Với độ chính xác được đặt thành 2 chữ số, chúng tôi nhận được:

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

thay vì 1M.

Làm thế nào chúng ta có thể chống lại điều đó?

Tất nhiên, chúng ta có thể kiểm tra nó một cách rõ ràng:

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

Nhưng chúng ta có thể làm tốt hơn không? Chúng ta có thể biết cách ordercắt giảm trước khi chúng ta thực hiện bước cuối cùng không?

Hóa ra chúng ta có thể.

Giả sử quy tắc làm tròn số thập phân 0,5, ifđiều kiện trên chuyển thành:

nhập mô tả hình ảnh ở đây

dẫn đến

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

cho

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

0

tham khảo Sridhar Ratnakumarcâu trả lời, cập nhật vào:

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)

và ví dụ đầu ra là:

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

0

Giải pháp này cũng có thể hấp dẫn bạn, tùy thuộc vào cách bạn làm việc:

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'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.