Tutorial de la biblioteca Python zlib

    Que es Python zlib

    La biblioteca zlib de Python proporciona una interfaz de Python para zlib Biblioteca C, que es una abstracci贸n de nivel superior para la DESINFLAR algoritmo de compresi贸n sin p茅rdidas. El formato de datos utilizado por la biblioteca se especifica en el RFC 1950 a 1952, que est谩 disponible en http://www.ietf.org/rfc/rfc1950.txt.

    El formato de compresi贸n zlib es de uso gratuito y no est谩 cubierto por ninguna patente, por lo que tambi茅n puede usarlo de manera segura en productos comerciales. Es un formato de compresi贸n sin p茅rdidas (lo que significa que no pierde ning煤n dato entre la compresi贸n y la descompresi贸n) y tiene la ventaja de ser port谩til en diferentes plataformas. Otro beneficio importante de este mecanismo de compresi贸n es que no expande los datos.

    El uso principal de la biblioteca zlib es en aplicaciones que requieren compresi贸n y descompresi贸n de datos arbitrarios, ya sea una cadena, contenido estructurado en memoria o archivos.

    Las funcionalidades m谩s importantes incluidas en esta biblioteca son la compresi贸n y la descompresi贸n. La compresi贸n y la descompresi贸n se pueden realizar como operaciones 煤nicas o dividiendo los datos en fragmentos como se ver铆a en un flujo de datos. Ambos modos de funcionamiento se explican en este art铆culo.

    Una de las mejores cosas, en mi opini贸n, de la biblioteca zlib es que es compatible con gzip formato / herramienta de archivo (que tambi茅n se basa en DEFLATE), que es una de las aplicaciones de compresi贸n m谩s utilizadas en sistemas Unix.

    Compresi贸n

    Comprimir una cadena de datos

    La biblioteca zlib nos proporciona la compress funci贸n, que se puede utilizar para comprimir una cadena de datos. La sintaxis de esta funci贸n es muy simple, tomando solo dos argumentos:

    compress(data, level=-1)
    

    Aqu铆 el argumento data contiene los bytes que se van a comprimir, y level es un valor entero que puede tomar los valores -1 o 0 a 9. Este par谩metro determina el nivel de compresi贸n, donde el nivel 1 es el m谩s r谩pido y produce el nivel m谩s bajo de compresi贸n. El nivel 9 es el m谩s lento, pero ofrece el nivel m谩s alto de compresi贸n. El valor -1 representa el valor predeterminado, que es el nivel 6. El valor predeterminado tiene un equilibrio entre velocidad y compresi贸n. El nivel 0 no produce compresi贸n.

    Un ejemplo de uso del compress El m茅todo en una cadena simple se muestra a continuaci贸n:

    import zlib
    import binascii
    
    data="Hello world"
    
    compressed_data = zlib.compress(data, 2)
    
    print('Original data: ' +  data)
    print('Compressed data: ' + binascii.hexlify(compressed_data))
    

    Y el resultado es el siguiente:

    $ python compress_str.py 
    Original data: Hello world
    Compressed data: 785ef348cdc9c95728cf2fca49010018ab043d
    

    Figura 1

    Si cambiamos el nivel a 0 (sin compresi贸n), la l铆nea 5 se convierte en:

    compressed_data = zlib.compress(data, 0)
    

    Y el nuevo resultado es:

    $ python compress_str.py 
    Original data: Hello world
    Compressed data: 7801010b00f4ff48656c6c6f20776f726c6418ab043d
    

    Figura 2

    Puede notar algunas diferencias al comparar las salidas al usar 0 o 2 para el nivel de compresi贸n. Usando un nivel de 2 obtenemos una cadena (formateada en hexadecimal) de longitud 38, mientras que con un nivel de 0 obtenemos una cadena hexadecimal con una longitud de 44. Esta diferencia de longitud se debe a la falta de compresi贸n al usar level 0.

    Si no formatea la cadena como hexadecimal, como he hecho en este ejemplo, y visualiza los datos de salida, probablemente notar谩 que la cadena de entrada a煤n se puede leer incluso despu茅s de haber sido “comprimida”, aunque tiene algunas formatear caracteres a su alrededor.

    Comprimir grandes flujos de datos

    Se pueden gestionar grandes flujos de datos con el compressobj() funci贸n, que devuelve un objeto de compresi贸n. La sintaxis es la siguiente:

    compressobj(level=-1, method=DEFLATED, wbits=15, memLevel=8, strategy=Z_DEFAULT_STRATEGY[, zdict])
    

    La principal diferencia entre los argumentos de esta funci贸n y la compress() la funci贸n es (aparte de la data par谩metro) el wbits argumento, que controla el tama帽o de la ventana y si el encabezado y el final se incluyen o no en la salida.

    Los posibles valores para wbits son:

    Valor Logaritmo del tama帽o de la ventana Salida

    +9 hasta +15Base 2Incluye encabezado y tr谩iler de zlib
    -9 hasta -15Valor absoluto de wbitsSin encabezado ni tr谩iler
    +25 hasta +31Bajo 4 bits del valorIncluye encabezado gzip y suma de comprobaci贸n final

    tabla 1

    los method El argumento representa el algoritmo de compresi贸n utilizado. Actualmente, el 煤nico valor posible es DEFLATED, que es el 煤nico m茅todo definido en el RFC 1950. El strategy El argumento se relaciona con el ajuste de compresi贸n. A menos que realmente sepa lo que est谩 haciendo, le recomiendo que no lo use y solo use el valor predeterminado.

    El siguiente c贸digo muestra c贸mo utilizar el compressobj() funci贸n:

    import zlib
    import binascii
    
    data="Hello world"
    
    compress = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -15)
    compressed_data = compress.compress(data)
    compressed_data += compress.flush()
    
    print('Original: ' + data)
    print('Compressed data: ' + binascii.hexlify(compressed_data))
    

    Despu茅s de ejecutar este c贸digo, el resultado es:

    $ python compress_obj.py 
    Original: Hello world
    Compressed data: f348cdc9c95728cf2fca490100
    

    figura 3

    Como podemos ver en la figura anterior, la frase “Hola mundo” se ha comprimido. Normalmente, este m茅todo se utiliza para comprimir flujos de datos que no caben en la memoria a la vez. Aunque este ejemplo no tiene un flujo de datos muy grande, tiene el prop贸sito de mostrar la mec谩nica de la compressobj() funci贸n.

    Tambi茅n puede ver c贸mo ser铆a 煤til en una aplicaci贸n m谩s grande en la que puede configurar la compresi贸n y luego pasar el objeto de compresi贸n a otros m茅todos / m贸dulos. Esto luego se puede usar para comprimir trozos de datos en serie.

    Tambi茅n puede ver c贸mo ser铆a 煤til en un escenario en el que tiene un flujo de datos para comprimir. En lugar de tener que acumular todos los datos en la memoria, puede simplemente llamar compress.compress(data) y compress.flush() en su fragmento de datos y luego pasar al siguiente fragmento mientras deja el anterior para que lo limpie la recolecci贸n de basura.

    Comprimir un archivo

    Tambi茅n podemos utilizar el compress() funci贸n para comprimir los datos en un archivo. La sintaxis es la misma que en el primer ejemplo.

    En el siguiente ejemplo, comprimiremos un archivo de imagen PNG llamado “logo.png” (que, debo se帽alar, ya es una versi贸n comprimida de la imagen original sin procesar).

    El c贸digo de ejemplo es el siguiente:

    import zlib
    
    original_data = open('logo.png', 'rb').read()
    compressed_data = zlib.compress(original_data, zlib.Z_BEST_COMPRESSION)
    
    compress_ratio = (float(len(original_data)) - float(len(compressed_data))) / float(len(original_data))
    
    print('Compressed: %d%%' % (100.0 * compress_ratio))
    

    En el c贸digo anterior, el zlib.compress(...) la l铆nea usa la constante Z_BEST_COMPRESSION, que, como su nombre indica, nos da el mejor nivel de compresi贸n que este algoritmo tiene para ofrecer. La siguiente l铆nea calcula el nivel de compresi贸n en funci贸n de la relaci贸n entre la longitud de los datos comprimidos y la longitud de los datos originales.

    El resultado es el siguiente:

    $ python compress_file.py 
    Compressed: 13%
    

    Figura 4

    Como podemos ver, el archivo se comprimi贸 en un 13%.

    La 煤nica diferencia entre este ejemplo y el primero es la fuente de los datos. Sin embargo, creo que es importante mostrarlo para que pueda tener una idea de qu茅 tipo de datos se pueden comprimir, ya sea solo una cadena ASCII o datos de imagen binaria. Simplemente lea sus datos del archivo como lo har铆a normalmente y llame al compress m茅todo.

    Guardar datos comprimidos en un archivo

    Los datos comprimidos tambi茅n se pueden guardar en un archivo para su uso posterior. El siguiente ejemplo muestra c贸mo guardar texto comprimido en un archivo:

    import zlib
    
    my_data="Hello world"
    
    compressed_data = zlib.compress(my_data, 2)
    
    f = open('outfile.txt', 'w')
    f.write(compressed_data)
    f.close()
    

    El ejemplo anterior comprime nuestra cadena simple “Hola mundo” y guarda los datos comprimidos en un archivo llamado “outfile.txt”. El archivo “outfile.txt”, cuando se abre con nuestro editor de texto, tiene el siguiente aspecto:

    Figura 5

    Descompresi贸n

    Descomprimir una cadena de datos

    Una cadena de datos comprimida se puede descomprimir f谩cilmente utilizando el decompress() funci贸n. La sintaxis es la siguiente:

    decompress(data, wbits=MAX_WBITS, bufsize=DEF_BUF_SIZE)
    

    Esta funci贸n descomprime los bytes en el data argumento. los wbits El argumento se puede utilizar para administrar el tama帽o del b煤fer de historial. El valor predeterminado coincide con el tama帽o de ventana m谩s grande. Tambi茅n solicita la inclusi贸n del encabezado y el avance del archivo comprimido. Los posibles valores son:

    Valor Logaritmo del tama帽o de la ventana Entrada

    +8 hasta +15Base 2Incluye encabezado y tr谩iler de zlib
    -8 hasta -15Valor absoluto de wbitsTransmisi贸n sin procesar sin encabezado ni tr谩iler
    +24 a +31 = 16 + (8 a 15)Bajo 4 bits del valorIncluye encabezado gzip y tr谩iler
    +40 a +47 = 32 + (8 a 15)Bajo 4 bits del valorformato zlib o gzip

    Tabla 2

    El valor inicial del tama帽o del b煤fer se indica en el bufsize argumento. Sin embargo, el aspecto importante de este par谩metro es que no necesita ser exacto, porque si se necesita un tama帽o de b煤fer adicional, se aumentar谩 autom谩ticamente.

    El siguiente ejemplo muestra c贸mo descomprimir la cadena de datos comprimidos en nuestro ejemplo anterior:

    import zlib
    
    data="Hello world"
    
    compressed_data = zlib.compress(data, 2)
    decompressed_data = zlib.decompress(compressed_data)
    
    print('Decompressed data: ' + decompressed_data)
    

    El resultado es el siguiente:

    $ python decompress_str.py 
    Decompressed data: Hello world
    

    Figura 5

    Descomprimir grandes flujos de datos

    La descompresi贸n de los flujos de big data puede requerir la administraci贸n de la memoria debido al tama帽o o la fuente de sus datos. Es posible que no pueda utilizar toda la memoria disponible para esta tarea (o no tenga suficiente memoria), por lo que decompressobj() El m茅todo le permite dividir un flujo de datos en varios fragmentos que puede descomprimir por separado.

    La sintaxis del decompressobj() la funci贸n es la siguiente:

    decompressobj(wbits=15[, zdict])
    

    Esta funci贸n devuelve un objeto de descompresi贸n, que utiliza para descomprimir los datos individuales. los wbits argumento tiene las mismas caracter铆sticas que en decompress() funci贸n explicada anteriormente.

    El siguiente c贸digo muestra c贸mo descomprimir un gran flujo de datos que se almacena en un archivo. En primer lugar, el programa crea un archivo llamado “outfile.txt”, que contiene los datos comprimidos. Tenga en cuenta que los datos se comprimen utilizando un valor de wbits igual a +15. Esto asegura la creaci贸n de un encabezado y un final en los datos.

    Luego, el archivo se descomprime utilizando fragmentos de datos. Nuevamente, en este ejemplo, el archivo no contiene una gran cantidad de datos, pero sin embargo, sirve para explicar el concepto de b煤fer.

    El c贸digo es el siguiente:

    import zlib
    
    data="Hello world"
    
    compress = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, +15)
    compressed_data = compress.compress(data)
    compressed_data += compress.flush()
    
    print('Original: ' + data)
    print('Compressed data: ' + compressed_data)
    
    f = open('compressed.dat', 'w')
    f.write(compressed_data)
    f.close()
    
    CHUNKSIZE = 1024
    
    data2 = zlib.decompressobj()
    my_file = open('compressed.dat', 'rb')            
    buf = my_file.read(CHUNKSIZE)
    
    # Decompress stream chunks
    while buf:
        decompressed_data = data2.decompress(buf)
        buf = my_file.read(CHUNKSIZE)
    
    decompressed_data += data2.flush()
    
    print('Decompressed data: ' + decompressed_data)
    
    my_file.close()
    

    Despu茅s de ejecutar el c贸digo anterior, obtenemos los siguientes resultados:

    $ python decompress_data.py 
    Original: Hello world
    Compressed data: x??H???W(?/?I?=
    Decompressed data: Hello world
    

    Figura 6

    Descomprimir datos de un archivo

    Los datos comprimidos contenidos en un archivo se pueden descomprimir f谩cilmente, como ha visto en ejemplos anteriores. Este ejemplo es muy similar al anterior en el sentido de que estamos descomprimiendo los datos que se originan en un archivo, excepto que en este caso volveremos a usar el 煤nico decompress m茅todo, que descomprime los datos en una 煤nica llamada al m茅todo. Esto es 煤til cuando sus datos son lo suficientemente peque帽os como para caber f谩cilmente en la memoria.

    Esto se puede ver en el siguiente ejemplo:

    import zlib
    
    compressed_data = open('compressed.dat', 'rb').read()
    decompressed_data = zlib.decompress(compressed_data)
    print(decompressed_data)
    

    El programa anterior abre el archivo “compressed.dat” creado en un ejemplo anterior, que contiene la cadena comprimida “Hola mundo”.

    En este ejemplo, una vez que los datos comprimidos se recuperan y almacenan en la variable compressed_data, el programa descomprime el flujo y muestra el resultado en la pantalla. Como el archivo contiene una peque帽a cantidad de datos, el ejemplo usa la decompress() funci贸n. Sin embargo, como muestra el ejemplo anterior, tambi茅n podr铆amos descomprimir los datos usando el decompressobj() funci贸n.

    Despu茅s de ejecutar el programa obtenemos el siguiente resultado:

    $ python decompress_file.py 
    Hello world
    

    Figura 7

    Terminando

    La biblioteca de Python zlib nos proporciona un conjunto 煤til de funciones para la compresi贸n de archivos usando el formato zlib. Las funciones compress() y decompress() se utilizan normalmente. Sin embargo, cuando hay limitaciones de memoria, las funciones compressobj() y decompressobj() est谩n disponibles para proporcionar m谩s flexibilidad al admitir la compresi贸n / descompresi贸n de flujos de datos. Estas funciones ayudan a dividir los datos en fragmentos m谩s peque帽os y manejables, que se pueden comprimir o descomprimir utilizando el compress() y decompress() funciones respectivamente.

    Tenga en cuenta que la biblioteca zlib tambi茅n tiene algunas caracter铆sticas m谩s de las que pudimos cubrir en este art铆culo. Por ejemplo, puede utilizar zlib para calcular la suma de comprobaci贸n de algunos datos para verificar su integridad cuando se descomprimen. Para obtener m谩s informaci贸n sobre funciones adicionales como esta, consulte el documentaci贸n oficial.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *