todos sirve que programación programa principiantes para niños lógica libros introducción ingenieros historia descargar con algoritmos python code-snippets filesize

python - sirve - Biblioteca reutilizable para obtener una versión humana legible del tamaño del archivo?



python para todos 3 (17)

Hay varios fragmentos en la web que le darán una función para devolver el tamaño legible para humanos del tamaño de los bytes:

>>> human_readable(2048) ''2 kilobytes'' >>>

Pero, ¿hay una biblioteca de Python que proporcione esto?


¿Qué tal un simple 2 liner:

def humanizeFileSize(filesize): p = int(math.floor(math.log(filesize, 2)/10)) return "%.3f%s" % (filesize/math.pow(1024,p), [''B'',''KiB'',''MiB'',''GiB'',''TiB'',''PiB'',''EiB'',''ZiB'',''YiB''][p])

Así es como funciona bajo el capó:

  1. Calcula el registro 2 (tamaño del archivo)
  2. Lo divide por 10 para obtener la unidad más cercana. (Por ejemplo, si el tamaño es de 5000 bytes, la unidad más cercana es Kb , por lo que la respuesta debería ser X KiB)
  3. Devuelve file_size/value_of_closest_unit junto con la unidad.

Sin embargo, no funciona si el tamaño del archivo es 0 o negativo (porque el registro no está definido para 0 y -ve números). Puede agregar cheques adicionales para ellos:

def humanizeFileSize(filesize): filesize = abs(filesize) if (filesize==0): return "0 Bytes" p = int(math.floor(math.log(filesize, 2)/10)) return "%0.2f %s" % (filesize/math.pow(1024,p), [''Bytes'',''KiB'',''MiB'',''GiB'',''TiB'',''PiB'',''EiB'',''ZiB'',''YiB''][p])

Ejemplos:

>>> humanizeFileSize(538244835492574234) ''478.06 PiB'' >>> humanizeFileSize(-924372537) ''881.55 MiB'' >>> humanizeFileSize(0) ''0 Bytes''

NOTA - Hay una diferencia entre Kb y KiB. KB significa 1000 bytes, mientras que KiB significa 1024 bytes. KB, MB, GB son todos múltiplos de 1000, mientras que KiB, MiB, GiB, etc. son todos múltiplos de 1024. Más sobre esto aquí


A partir de todas las respuestas anteriores, aquí está mi opinión sobre esto. Es un objeto que almacenará el tamaño del archivo en bytes como un entero. Pero cuando intenta imprimir el objeto, automáticamente obtiene una versión humana legible.

class Filesize(object): """ Container for a size in bytes with a human readable representation Use it like this:: >>> size = Filesize(123123123) >>> print size ''117.4 MB'' """ chunk = 1024 units = [''bytes'', ''KB'', ''MB'', ''GB'', ''TB'', ''PB''] precisions = [0, 0, 1, 2, 2, 2] def __init__(self, size): self.size = size def __int__(self): return self.size def __str__(self): if self.size == 0: return ''0 bytes'' from math import log unit = self.units[min(int(log(self.size, self.chunk)), len(self.units) - 1)] return self.format(unit) def format(self, unit): if unit not in self.units: raise Exception("Not a valid file size unit: %s" % unit) if self.size == 1 and unit == ''bytes'': return ''1 byte'' exponent = self.units.index(unit) quotient = float(self.size) / self.chunk**exponent precision = self.precisions[exponent] format_string = ''{:.%sf} {}'' % (precision) return format_string.format(quotient, unit)


Abordando la cuestión anterior de "una tarea demasiado pequeña para requerir una biblioteca" mediante una implementación sencilla:

def sizeof_fmt(num, suffix=''B''): for unit in ['''',''Ki'',''Mi'',''Gi'',''Ti'',''Pi'',''Ei'',''Zi'']: if abs(num) < 1024.0: return "%3.1f%s%s" % (num, unit, suffix) num /= 1024.0 return "%.1f%s%s" % (num, ''Yi'', suffix)

Apoyos:

  • todos los prefijos binarios actualmente conocidos
  • números negativos y positivos
  • números más grandes que 1000 Yobibytes
  • unidades arbitrarias (¡quizás te gusta contar en Gibibits!)

Ejemplo:

>>> sizeof_fmt(168963795964) ''157.4GiB''

por Fred Cirera


Aquí está mi versión. No usa un for-loop. Tiene una complejidad constante, O ( 1 ), y en teoría es más eficiente que las respuestas aquí que usan un for-loop.

from math import log unit_list = zip([''bytes'', ''kB'', ''MB'', ''GB'', ''TB'', ''PB''], [0, 0, 1, 2, 2, 2]) def sizeof_fmt(num): """Human friendly file size""" if num > 1: exponent = min(int(log(num, 1024)), len(unit_list) - 1) quotient = float(num) / 1024**exponent unit, num_decimals = unit_list[exponent] format_string = ''{:.%sf} {}'' % (num_decimals) return format_string.format(quotient, unit) if num == 0: return ''0 bytes'' if num == 1: return ''1 byte''

Para que quede más claro lo que está sucediendo, podemos omitir el código para el formato de cadena. Estas son las líneas que realmente hacen el trabajo:

exponent = int(log(num, 1024)) quotient = num / 1024**exponent unit_list[exponent]


Aunque sé que esta pregunta es antigua, recientemente se me ocurrió una versión que evita los bucles, usando log2 para determinar el orden de tamaño que funciona como un cambio y un índice en la lista de sufijos:

from math import log2 _suffixes = [''bytes'', ''KiB'', ''MiB'', ''GiB'', ''TiB'', ''PiB'', ''EiB'', ''ZiB'', ''YiB''] def file_size(size): # determine binary order in steps of size 10 # (coerce to int, // still returns a float) order = int(log2(size) / 10) if size else 0 # format file size # (.4g results in rounded numbers for exact matches and max 3 decimals, # should never resort to exponent values) return ''{:.4g} {}''.format(size / (1 << (order * 10)), _suffixes[order])

Sin embargo, podría considerarse antiponético por su legibilidad :)


DiveIntoPython3 también talks sobre esta función.


Esto hará lo que necesita en casi cualquier situación, es personalizable con argumentos opcionales, y como puede ver, es casi autodocumentado:

from math import log def pretty_size(n,pow=0,b=1024,u=''B'',pre=['''']+[p+''i''for p in''KMGTPEZY'']): pow,n=min(int(log(max(n*b**pow,1),b)),len(pre)-1),n*b**pow return "%%.%if %%s%%s"%abs(pow%(-pow-1))%(n/b**float(pow),pre[pow],u)

Ejemplo de salida:

>>> pretty_size(42) ''42 B'' >>> pretty_size(2015) ''2.0 KiB'' >>> pretty_size(987654321) ''941.9 MiB'' >>> pretty_size(9876543210) ''9.2 GiB'' >>> pretty_size(0.5,pow=1) ''512 B'' >>> pretty_size(0) ''0 B''

Personalizaciones avanzadas:

>>> pretty_size(987654321,b=1000,u=''bytes'',pre=['''',''kilo'',''mega'',''giga'']) ''987.7 megabytes'' >>> pretty_size(9876543210,b=1000,u=''bytes'',pre=['''',''kilo'',''mega'',''giga'']) ''9.9 gigabytes''

Este código es compatible con Python 2 y Python 3. El cumplimiento de PEP8 es un ejercicio para el lector. Recuerde, es la salida que es bonita.

Actualizar:

Si necesita miles de comas, solo aplique la extensión obvia:

def prettier_size(n,pow=0,b=1024,u=''B'',pre=['''']+[p+''i''for p in''KMGTPEZY'']): r,f=min(int(log(max(n*b**pow,1),b)),len(pre)-1),''{:,.%if} %s%s'' return (f%(abs(r%(-r-1)),pre[r],u)).format(n*b**pow/b**float(r))

Por ejemplo:

>>> pretty_units(987654321098765432109876543210) ''816,968.5 YiB''


Me gusta la precisión fija de la versión decimal de senderle , así que aquí hay una especie de híbrido de eso con la respuesta de joctee anterior (¿sabías que podrías tomar registros con bases no enteras?):

from math import log def human_readable_bytes(x): # hybrid of https://.com/a/10171475/2595465 # with https://.com/a/5414105/2595465 if x == 0: return ''0'' magnitude = int(log(abs(x),10.24)) if magnitude > 16: format_str = ''%iP'' denominator_mag = 15 else: float_fmt = ''%2.1f'' if magnitude % 3 == 1 else ''%1.2f'' illion = (magnitude + 1) // 3 format_str = float_fmt + ['''', ''K'', ''M'', ''G'', ''T'', ''P''][illion] return (format_str % (x * 1.0 / (1024 ** illion))).lstrip(''0'')


Modern Django tiene una plantilla de filesizeformat formato de filesizeformat :

Formatea el valor como un tamaño de archivo human-readable (es decir, ''13 KB '','' 4.1 MB '','' 102 bytes '', etc.).

Por ejemplo:

{{ value|filesizeformat }}

Si el valor es 123456789, la salida sería 117.7 MB.

Más información: https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#filesizeformat


Riffing en el fragmento provisto como alternativa a hurry.filesize (), aquí hay un fragmento que da números de precisión variables basados ​​en el prefijo utilizado. No es tan escueto como algunos fragmentos, pero me gustan los resultados.

def human_size(size_bytes): """ format a size in bytes into a ''human'' file size, e.g. bytes, KB, MB, GB, TB, PB Note that bytes/KB will be reported in whole numbers but MB and above will have greater precision e.g. 1 byte, 43 bytes, 443 KB, 4.3 MB, 4.43 GB, etc """ if size_bytes == 1: # because I really hate unnecessary plurals return "1 byte" suffixes_table = [(''bytes'',0),(''KB'',0),(''MB'',1),(''GB'',2),(''TB'',2), (''PB'',2)] num = float(size_bytes) for suffix, precision in suffixes_table: if num < 1024.0: break num /= 1024.0 if precision == 0: formatted_size = "%d" % num else: formatted_size = str(round(num, ndigits=precision)) return "%s %s" % (formatted_size, suffix)


Saliendo de la solución Sridhar Ratnakumar, me gusta un poco mejor. Funciona en Python 3.6+

def human_readable_size(size, decimal_places): for unit in ['''',''KB'',''MB'',''GB'',''TB'']: if size < 1024.0: break size /= 1024.0 return f"{size:.{decimal_places}f}{unit}"


Si está utilizando Django instalado, también puede probar filesizeformat :

from django.template.defaultfilters import filesizeformat filesizeformat(1073741824) => "1.0 GB"


Siempre debe haber uno de esos tipos. Bueno, hoy soy yo. Aquí hay una solución de una sola línea, o dos líneas si cuenta la firma de la función.

def human_size(bytes, units=['' bytes'',''KB'',''MB'',''GB'',''TB'', ''PB'', ''EB'']): """ Returns a human readable string reprentation of bytes""" return str(bytes) + units[0] if bytes < 1024 else human_size(bytes>>10, units[1:])

>>> human_size(123) 123 bytes >>> human_size(123456789) 117GB


Una biblioteca que tiene toda la funcionalidad que parece que estás buscando es humanize . humanize.naturalsize() parece hacer todo lo que estás buscando.


Una de esas bibliotecas es hurry.filesize .

>>> from hurry.filesize import alternative >>> size(1, system=alternative) ''1 byte'' >>> size(10, system=alternative) ''10 bytes'' >>> size(1024, system=alternative) ''1 KB''


Usar cualquiera de las potencias de 1000 o kibibytes sería más amigable con el estándar:

def sizeof_fmt(num, use_kibibyte=True): base, suffix = [(1000.,''B''),(1024.,''iB'')][use_kibibyte] for x in [''B''] + map(lambda x: x+suffix, list(''kMGTP'')): if -base < num < base: return "%3.1f %s" % (num, x) num /= base return "%3.1f %s" % (num, x)

PD Nunca confíes en una biblioteca que imprime miles con el sufijo K (mayúscula) :)


def human_readable_data_quantity(quantity, multiple=1024): if quantity == 0: quantity = +0 SUFFIXES = ["B"] + [i + {1000: "B", 1024: "iB"}[multiple] for i in "KMGTPEZY"] for suffix in SUFFIXES: if quantity < multiple or suffix == SUFFIXES[-1]: if suffix == SUFFIXES[0]: return "%d%s" % (quantity, suffix) else: return "%.1f%s" % (quantity, suffix) else: quantity /= multiple