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.

Respuestas a la pregunta(2)

Su respuesta a la pregunta