#!/usr/bin/env python
"""
Bytes-to-human / human-to-bytes converter.
Based on: http://goo.gl/kTQMs
Working with Python 2.x and 3.x.
Author: Giampaolo Rodola' <g.rodola [AT] gmail [DOT] com>
License: MIT
"""
# see: http://goo.gl/kTQMs
_customary = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
_customary_ext = ('byte', 'kilo', 'mega', 'giga', 'tera',
'peta', 'exa', 'zetta', 'iotta')
_iec = ('Bi', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi')
_iec_ext = ('byte', 'kibi', 'mebi', 'gibi', 'tebi', 'pebi',
'exbi', 'zebi', 'yobi')
_symbols_set = (_customary, _customary_ext, _iec, _iec_ext)
_symbols_map = dict(customary=_customary, customary_ext=_customary_ext,
iec=_iec, iec_ext=_iec_ext)
def bytes2human(n, format="%(value).1f %(symbol)s", symbols="customary"):
"""
Convert n bytes into a human readable string based on format.
symbols can be either "customary", "customary_ext", "iec" or "iec_ext",
see: http://goo.gl/kTQMs
>>> bytes2human(0)
'0.0 B'
>>> bytes2human(0.9)
'0.0 B'
>>> bytes2human(1)
'1.0 B'
>>> bytes2human(1.9)
'1.0 B'
>>> bytes2human(1024)
'1.0 K'
>>> bytes2human(1048576)
'1.0 M'
>>> bytes2human(1099511627776127398123789121)
'909.5 Y'
>>> bytes2human(9856, symbols="customary")
'9.6 K'
>>> bytes2human(9856, symbols="customary_ext")
'9.6 kilo'
>>> bytes2human(9856, symbols="iec")
'9.6 Ki'
>>> bytes2human(9856, symbols="iec_ext")
'9.6 kibi'
>>> bytes2human(10000, "%(value).1f %(symbol)s/sec")
'9.8 K/sec'
>>> # precision can be adjusted by playing with %f operator
>>> bytes2human(10000, format="%(value).5f %(symbol)s")
'9.76562 K'
"""
n = int(n)
if n < 0:
raise ValueError("n < 0")
symbols = _symbols_map[symbols]
prefix = {}
for i, s in enumerate(symbols[1:]):
prefix[s] = 1 << (i+1)*10
for symbol in reversed(symbols[1:]):
if n >= prefix[symbol]:
value = float(n) / prefix[symbol]
return format % locals()
return format % dict(symbol=symbols[0], value=n)
def human2bytes(s):
"""
Attempts to guess the string format based on default symbols
set and return the corresponding bytes as an integer.
When unable to recognize the format ValueError is raised.
>>> human2bytes('0 B')
0
>>> human2bytes('1 K')
1024
>>> human2bytes('1 M')
1048576
>>> human2bytes('1 Gi')
1073741824
>>> human2bytes('1 tera')
1099511627776
>>> human2bytes('0.5kilo')
512
>>> human2bytes('0.1 byte')
0
>>> human2bytes('1 k') # k is an alias for K
1024
>>> human2bytes('12 foo')
Traceback (most recent call last):
...
ValueError: can't interpret '12 foo'
"""
init = s
num = ""
while s and s[0:1].isdigit() or s[0:1] == '.':
num += s[0]
s = s[1:]
num = float(num)
letter = s.strip()
for sset in _symbols_set:
if letter in sset:
break
else:
if letter == 'k':
# treat 'k' as an alias for 'K' as per: http://goo.gl/kTQMs
sset = _customary
letter = letter.upper()
else:
raise ValueError("can't interpret %r" % init)
prefix = {sset[0]:1}
for i, s in enumerate(sset[1:]):
prefix[s] = 1 << (i+1)*10
return int(num * prefix[letter])
if __name__ == "__main__":
import doctest
doctest.testmod()
Diff to Previous Revision
--- revision 10 2012-01-19 00:20:05
+++ revision 11 2012-01-19 00:42:01
@@ -27,36 +27,36 @@
symbols can be either "customary", "customary_ext", "iec" or "iec_ext",
see: http://goo.gl/kTQMs
- >>> bytes2human(0)
- '0.0 B'
- >>> bytes2human(0.9)
- '0.0 B'
- >>> bytes2human(1)
- '1.0 B'
- >>> bytes2human(1.9)
- '1.0 B'
- >>> bytes2human(1024)
- '1.0 K'
- >>> bytes2human(1048576)
- '1.0 M'
- >>> bytes2human(1099511627776127398123789121)
- '909.5 Y'
+ >>> bytes2human(0)
+ '0.0 B'
+ >>> bytes2human(0.9)
+ '0.0 B'
+ >>> bytes2human(1)
+ '1.0 B'
+ >>> bytes2human(1.9)
+ '1.0 B'
+ >>> bytes2human(1024)
+ '1.0 K'
+ >>> bytes2human(1048576)
+ '1.0 M'
+ >>> bytes2human(1099511627776127398123789121)
+ '909.5 Y'
- >>> bytes2human(9856, symbols="customary")
- '9.6 K'
- >>> bytes2human(9856, symbols="customary_ext")
- '9.6 kilo'
- >>> bytes2human(9856, symbols="iec")
- '9.6 Ki'
- >>> bytes2human(9856, symbols="iec_ext")
- '9.6 kibi'
+ >>> bytes2human(9856, symbols="customary")
+ '9.6 K'
+ >>> bytes2human(9856, symbols="customary_ext")
+ '9.6 kilo'
+ >>> bytes2human(9856, symbols="iec")
+ '9.6 Ki'
+ >>> bytes2human(9856, symbols="iec_ext")
+ '9.6 kibi'
- >>> bytes2human(10000, "%(value).1f %(symbol)s/sec")
- '9.8 K/sec'
+ >>> bytes2human(10000, "%(value).1f %(symbol)s/sec")
+ '9.8 K/sec'
- >>> # precision can be adjusted by playing with %f operator
- >>> bytes2human(10000, format="%(value).5f %(symbol)s")
- '9.76562 K'
+ >>> # precision can be adjusted by playing with %f operator
+ >>> bytes2human(10000, format="%(value).5f %(symbol)s")
+ '9.76562 K'
"""
n = int(n)
if n < 0:
@@ -77,23 +77,27 @@
set and return the corresponding bytes as an integer.
When unable to recognize the format ValueError is raised.
- >>> human2bytes('0 B')
- 0
- >>> human2bytes('1 K')
- 1024
- >>> human2bytes('1 M')
- 1048576
- >>> human2bytes('1 Gi')
- 1073741824
- >>> human2bytes('1 tera')
- 1099511627776
+ >>> human2bytes('0 B')
+ 0
+ >>> human2bytes('1 K')
+ 1024
+ >>> human2bytes('1 M')
+ 1048576
+ >>> human2bytes('1 Gi')
+ 1073741824
+ >>> human2bytes('1 tera')
+ 1099511627776
- >>> human2bytes('0.5kilo')
- 512
- >>> human2bytes('0.1 byte')
- 0
- >>> human2bytes('1 k') # k is an alias for K
- 1024
+ >>> human2bytes('0.5kilo')
+ 512
+ >>> human2bytes('0.1 byte')
+ 0
+ >>> human2bytes('1 k') # k is an alias for K
+ 1024
+ >>> human2bytes('12 foo')
+ Traceback (most recent call last):
+ ...
+ ValueError: can't interpret '12 foo'
"""
init = s
num = ""