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 *