Bytes a humanos legibles, y de vuelta. sin pérdida de datos
Necesito convertir cadenas que contengan el uso de memoria en bytes, como:1048576
(que es 1M) en exactamente eso, una versión legible por humanos, y viceversa.
Nota: Ya miré aquí:¿Biblioteca reutilizable para obtener una versión humana del tamaño del archivo?
Y aquí (aunque no sea python):¿Cómo convertir el tamaño de la memoria legible humana en bytes?
Nada me ha ayudado hasta ahora, así que busqué en otra parte.
He encontrado algo que hace esto por mí aquí:http://code.google.com/p/pyftpdlib/source/browse/trunk/test/bench.py?spec=svn984&r=984#137 o, para una URL más corta:http://goo.gl/zeJZl
El código:
def bytes2human(n, format="%(value)i%(symbol)s"):
"""
>>> bytes2human(10000)
'9K'
>>> bytes2human(100001221)
'95M'
"""
symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
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)
Y también una función para la conversión de la otra manera (mismo sitio):
def human2bytes(s):
"""
>>> human2bytes('1M')
1048576
>>> human2bytes('1G')
1073741824
"""
symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
letter = s[-1:].strip().upper()
num = s[:-1]
assert num.isdigit() and letter in symbols
num = float(num)
prefix = {symbols[0]:1}
for i, s in enumerate(symbols[1:]):
prefix[s] = 1 << (i+1)*10
return int(num * prefix[letter])
Esto es genial y todo, pero tiene alguna pérdida de información, por ejemplo:
>>> bytes2human(10000)
'9K'
>>> human2bytes('9K')
9216
Para intentar resolver esto, cambio el formato de la función.bytes2human
Dentro:format="%(value).3f%(symbol)s")
Lo cual es mucho mejor, dándome estos resultados:
>>> bytes2human(10000)
'9.766K'
pero cuando trato de convertirlos de nuevo con elhuman2bytes
función:
>>> human2bytes('9.766K')
Traceback (most recent call last):
File "<pyshell#366>", line 1, in <module>
human2bytes('9.766K')
File "<pyshell#359>", line 12, in human2bytes
assert num.isdigit() and letter in symbols
AssertionError
Esto se debe a la.
Entonces, mi pregunta es, ¿cómo puedo convertir una versión legible por humanos de nuevo a una versión de byte, sin pérdida de datos?
Nota: Sé que los 3 decimales son también un poco de pérdida de datos. Pero para los propósitos de esta pregunta, ignoremos que por ahora, siempre puedo cambiar eso a algo más grande.