#!/usr/bin/env python3 import argparse import sys SYMBOLS = ('kilo', 'mega', 'giga', 'tera', 'peta', 'exa', 'zetta', 'iotta') def get_bytes(data_queue): """Parses list of strings, ints or floats representing data amounts (e.g 1MB, 2mb, 3M) to a list of bytes. Parses all types listed in SYMBOLS. >>> add_bytes([500, "1.1mb", "23KB"]) [500.0, 1153433.6, 23552.0] """ output = [] for item in data_queue: if type(item) in (int, float): output.append(float(item)) continue if item[-1] in "bB": # we don't need to worry about bytes item = item[:-1] item = item.lower().strip() # for better matching try: output.append(float(item)) continue except ValueError: pass power = 0 # so `if not power` works for x, symbol in enumerate(SYMBOLS): if symbol[0] in item: power = x + 1 if not power: # string was not a match continue item = float("".join(c for c in item if c in "0123456789.")) output.append(item * (1024 ** power)) return output def parse_bytes(byte_list, precision=2): """ Parses list of ints or floats into summed 'human' amount rounded to 2dp. >>> parse_bytes([500, 1153433.6, 23552]) "1.12MB" """ total = sum(byte_list) i = -1 while total > 1024: i += 1 total = total / 1024 return ("{:.%sf}{}B" % precision).format(total, SYMBOLS[i][0].upper()) def main(): parser = argparse.ArgumentParser() parser.add_argument("amounts", help="Array of data amounts to be processed", nargs="+") parser.add_argument("-p", "--precision", help="Number of decimal places in the output") args = parser.parse_args() byte_list = get_bytes(args.amounts) print(parse_bytes(byte_list, args.precision or 2)) return 0 if __name__ == "__main__": sys.exit(main())