将人类可读的文件大小解析为字节


example_strings = ["10.43 KB", "11 GB", "343.1 MB"]

我想将所有这些字符串转换为字节。到目前为止,我想出了这个:

def parseSize(size):
    if size.endswith(" B"):
        size = int(size.rstrip(" B"))
    elif size.endswith(" KB"):
        size = float(size.rstrip(" KB")) * 1000
    elif size.endswith(" MB"):
        size = float(size.rstrip(" MB")) * 1000000
    elif size.endswith(" GB"):
        size = float(size.rstrip(" GB")) * 10000000000
    elif size.endswith(" TB"):
        size = float(size.rstrip(" TB")) * 10000000000000
    return int(size)

但我不喜欢它,也不认为它有效。我只能找到做相反事情的模块。

这是一个稍微漂亮的版本。可能没有模块,只需内联定义函数即可。它非常小且可读。

units = {"B": 1, "KB": 10**3, "MB": 10**6, "GB": 10**9, "TB": 10**12}
# Alternative unit definitions, notably used by Windows:
# units = {"B": 1, "KB": 2**10, "MB": 2**20, "GB": 2**30, "TB": 2**40}
def parse_size(size):
    number, unit = [string.strip() for string in size.split()]
    return int(float(number)*units[unit])

example_strings = ["10.43 KB", "11 GB", "343.1 MB"]
for example_string in example_strings:
    print(parse_size(example_string))
10680
11811160064
359766426

(请注意,不同的地方对 KB、MB 等的定义使用略有不同的约定 - 要么使用 10**3 = 1000 的幂,要么使用 2**10 = 1024 的幂。如果您的上下文是 Windows,则需要使用后者。如果您的上下文是 Mac OS,您将需要使用前者。

为了回答OPs的问题,似乎确实有一个模块,人性化:

pip install humanfriendly

然后

>>> import humanfriendly
>>> user_input = raw_input("Enter a readable file size: ")
Enter a readable file size: 16G
>>> num_bytes = humanfriendly.parse_size(user_input)
>>> print num_bytes
16000000000
>>> print "You entered:", humanfriendly.format_size(num_bytes)
You entered: 16 GB
>>> print "You entered:", humanfriendly.format_size(num_bytes, binary=True)
You entered: 14.9 GiB

与谷歌中出现的其他所有内容相比,我喜欢 Denziloe 的答案,但它

  • 数字和单位之间需要空格
  • 未处理小写单元
  • 假设kb是 1000 而不是 1024,依此类推。 (感谢米利斯纳多年前试图指出这一点。 也许我们的假设太老派了,但我也不认为大多数软件赶上新的假设。

所以我把它调整成这样:

import re
# based on https://stackoverflow.com/a/42865957/2002471
units = {"B": 1, "KB": 2**10, "MB": 2**20, "GB": 2**30, "TB": 2**40}
def parse_size(size):
    size = size.upper()
    #print("parsing size ", size)
    if not re.match(r' ', size):
        size = re.sub(r'([KMGT]?B)', r' 1', size)
    number, unit = [string.strip() for string in size.split()]
    return int(float(number)*units[unit])
example_strings = ["1024b", "10.43 KB", "11 GB", "343.1 MB", "10.43KB", "11GB", "343.1MB", "10.43 kb", "11 gb", "343.1 mb", "10.43kb", "11gb", "343.1mb"]
for example_string in example_strings:
        print(example_string, parse_size(example_string))

我们可以通过检查输出来验证:

$ python humansize.py 
('1024b', 1024)
('10.43 KB', 10680)
('11 GB', 11811160064)
('343.1 MB', 359766425)
('10.43KB', 10680)
('11GB', 11811160064)
('343.1MB', 359766425)
('10.43 kb', 10680)
('11 gb', 11811160064)
('343.1 mb', 359766425)
('10.43kb', 10680)
('11gb', 11811160064)
('343.1mb', 359766425)

根据小鸡的答案,只使用正则表达式来解析大小,接受整数大小。

UNITS = {None: 1, "B": 1, "KB": 2 ** 10, "MB": 2 ** 20, "GB": 2 ** 30, "TB": 2 ** 40}

def parse_human_size(size):
    """
    >>> examples = [12345, "123214", "1024b", "10.43 KB", "11 GB", "343.1 MB", "10.43KB", "11GB", "343.1MB", "10.43 kb"]
    >>> for s in examples:
        print('[', s, ']', parse_human_size(s))
    """
    if isinstance(size, int):
        return size
    m = re.match(r'^(d+(?:.d+)?)s*([KMGT]?B)?$', size.upper())
    if m:
        number, unit = m.groups()
        return int(float(number) * UNITS[unit])
    raise ValueError("Invalid human size")
import re
def parse_size(size):
    units = {"B": 1, "KB": 2**10, "MB": 2**20, "GB": 2**30, "TB": 2**40 ,
             "":  1, "KIB": 10**3, "MIB": 10**6, "GIB": 10**9, "TIB": 10**12}
    m = re.match(r'^([d.]+)s*([a-zA-Z]{0,3})$', str(size).strip())
    number, unit = float(m.group(1)), m.group(2).upper()
    return int(number*units[unit])

代码搜索包含字符串的度量单位。 一旦找到。 使用另一个正则表达式提取数字。 一旦完成了这两件事。 将值计算为字节。 如果未指定该值,它将尝试将其视为字节,但如果不可能转换,则函数返回 0。

def calculate(data):
    convertion={"G":1073741824,"M":1048576,"K":1024,"B":1}
    result=re.findall(r'G|M|K|B',data,re.IGNORECASE)
    if len(result)>=1:
        number=re.findall(r'[-+]?d*.d+|d+', data)
        number=float(number[0])
        return int(number*convertion[result[0].upper()])
    else:
      number=re.findall(r'[-+]?d*.d+|d+', data)
      if len(number)>=1:
        number=float(number[0])
        return int(number*convertion["B"])
      else:
          return 0

编辑:我错过了另一个答案,它指出了另一个用于解决此问题的人类友好包,并且这个包只是为这种事情而构建的(而不是我建议从为完全不同的目的构建的包中挖走实用程序函数(。所以+1这个答案。

我最终来到这里是因为我想避免依赖,但对于那些不介意的人,您可以在dask.utils.parse_bytes中找到适合此的实用程序。

import dask.utils
# supports good range of human-readable units
dask.utils.parse_bytes('150Gi')
161061273600
dask.utils.parse_bytes('150GB')
150000000000
# and potential spelling variants
dask.utils.parse_bytes('150Gb')
150000000000
无论如何,这是

文档,这是源代码。Dask是python中并行计算的框架,来为花哨的utils而来,为并发:)而留下来

相关内容

最新更新