deflate — compresión y descompresión deflate

Este módulo permite la compresión y descompresión de datos binarios con el algoritmo DEFLATE (usado habitualmente en la biblioteca zlib y el archivador gzip). Añadido en MicroPython v1.21.

Disponibilidad en las placas compatibles con OpenMV:

Placa

Descompresión

Compresión

OpenMV Cam N6

No

OpenMV AE3

OpenMV Cam RT1062

OpenMV Cam Pure Thermal

No

OpenMV Cam M4

No

OpenMV Cam M7

No

OpenMV Cam H7

No

OpenMV Cam H7 Plus

No

Arduino Giga

No

Arduino Portenta H7

No

Arduino Nicla Vision

No

Arduino Nano 33 BLE Sense

No

Arduino Nano RP2040 Connect

No

Clases

class deflate.DeflateIO(stream: Any, format: int = AUTO, wbits: int = 0, close: bool = False, /)

Esta clase puede usarse para envolver un stream que sea cualquier objeto similar a un stream como un archivo, un socket o un stream (incluyendo io.BytesIO). Es en sí mismo un stream e implementa los métodos estándar read/readinto/write/close.

El stream debe ser un stream bloqueante. Los streams no bloqueantes no están admitidos actualmente.

El format puede establecerse en cualquiera de las constantes definidas a continuación, y por defecto es AUTO, que para la descompresión detectará automáticamente streams gzip o zlib, y para la compresión generará un stream sin procesar.

El parámetro wbits establece el logaritmo en base 2 del tamaño de la ventana del diccionario DEFLATE. Así, por ejemplo, establecer wbits en 10 fija el tamaño de la ventana en 1024 bytes. Los valores válidos van de 5 a 15 inclusive (correspondientes a tamaños de ventana de 32 a 32k bytes).

Si wbits se establece en 0 (el valor por defecto), entonces para la compresión se usará un tamaño de ventana de 256 bytes (como si wbits se hubiera establecido en 8). Para la descompresión, depende del formato:

  • RAW usará 256 bytes (correspondiente a wbits establecido en 8).

  • ZLIB (o AUTO con zlib detectado) usará el valor de la cabecera zlib.

  • GZIP (o AUTO con gzip detectado) usará 32 kilobytes (correspondiente a wbits establecido en 15).

Consulta las notas sobre el tamaño de la ventana más abajo para obtener más información sobre el tamaño de la ventana, y los streams zlib y gzip.

Si close se establece en True, entonces el stream subyacente se cerrará automáticamente cuando se cierre el stream deflate.DeflateIO. Esto es útil si quieres devolver un stream deflate.DeflateIO que envuelve otro stream y que el llamador no necesite saber cómo gestionar el stream subyacente.

Si la compresión está habilitada, una instancia dada de deflate.DeflateIO admite tanto lectura como escritura. Por ejemplo, se puede envolver un stream bidireccional como un socket, lo que permite compresión/descompresión en ambas direcciones.

Constantes

Las cuatro constantes format seleccionan el encuadre aplicado alrededor del flujo de bits deflate sin procesar.

deflate.AUTO: int

Para la descompresión, detecta automáticamente el formato de entrada inspeccionando los primeros bytes del stream (zlib o gzip). Para la compresión, genera un stream deflate sin procesar sin cabecera ni cola (equivalente a RAW).

deflate.RAW: int

Un stream deflate sin procesar (sin cabecera, sin cola, sin suma de verificación). Como el stream no contiene metadatos, el descompresor no puede recuperar el tamaño de la ventana a partir de los datos, por lo que wbits debe establecerse explícitamente al descomprimir; de lo contrario, la ventana por defecto de 256 bytes puede ser demasiado pequeña.

deflate.ZLIB: int

Un stream deflate envuelto en zlib según se define en el RFC 1950: una cabecera de 2 bytes que registra el tamaño de la ventana, la carga útil deflate y una suma de verificación Adler-32 al final. Compacto y autodescriptivo; muy adecuado para uso embebido.

deflate.GZIP: int

Un stream deflate envuelto en gzip según se define en el RFC 1952: una cabecera con metadatos opcionales de nombre de archivo/marca de tiempo, la carga útil deflate y un CRC-32 al final más la longitud sin comprimir. Este es el formato producido por la herramienta de línea de comandos gzip y por gzip.GzipFile. La cabecera no registra el tamaño de la ventana, por lo que el descompresor debe asumir 32 KiB a menos que se establezca wbits.

Ejemplos

Un caso de uso típico de deflate.DeflateIO es leer o escribir un archivo comprimido desde el almacenamiento:

import deflate

# Writing a zlib-compressed stream (uses the default window size of 256 bytes).
with open("data.z", "wb") as f:
    with deflate.DeflateIO(f, deflate.ZLIB) as d:
        # Use d.write(...) etc

# Reading a zlib-compressed stream (auto-detect window size).
with open("data.z", "rb") as f:
    with deflate.DeflateIO(f, deflate.ZLIB) as d:
        # Use d.read(), d.readinto(), etc.

Como deflate.DeflateIO es un stream, puede usarse por ejemplo con json.dump() y json.load() (y en cualquier otro lugar donde se puedan usar streams):

import deflate, json

# Write a dictionary as JSON in gzip format, with a
# small (64 byte) window size.
config = { ... }
with open("config.gz", "wb") as f:
    with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
        json.dump(config, f)

# Read back that dictionary.
with open("config.gz", "rb") as f:
    with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
        config = json.load(f)

Si tus datos de origen no están en formato de stream, puedes usar io.BytesIO para convertirlos en un stream apto para usar con deflate.DeflateIO:

import deflate, io

# Decompress a bytes/bytearray value.
compressed_data = get_data_z()
with deflate.DeflateIO(io.BytesIO(compressed_data), deflate.ZLIB) as d:
    decompressed_data = d.read()

# Compress a bytes/bytearray value.
uncompressed_data = get_data()
stream = io.BytesIO()
with deflate.DeflateIO(stream, deflate.ZLIB) as d:
    d.write(uncompressed_data)
compressed_data = stream.getvalue()

Tamaño de la ventana deflate

El tamaño de la ventana limita hasta qué punto atrás en el stream puede hacer referencia el (des)compresor. Aumentar el tamaño de la ventana mejorará la compresión, pero requerirá más memoria y hará que el compresor sea más lento.

Si un stream de entrada se comprimió con un tamaño de ventana dado, entonces DeflateIO usando un tamaño de ventana más pequeño fallará a mitad de camino durante la descompresión con OSError, pero solo si una retro-referencia realmente apunta más atrás que el tamaño de la ventana del descompresor. Esto significa que puede ser posible descomprimir con un tamaño de ventana más pequeño. Por ejemplo, este sería trivialmente el caso si los datos originales sin comprimir son más cortos que el tamaño de la ventana.

Descompresión

El formato zlib incluye una cabecera que especifica el tamaño de la ventana que se usó para comprimir los datos. Esto indica el tamaño máximo de ventana necesario para descomprimir este stream. Si este valor de la cabecera es menor que el valor de wbits especificado (o si wbits no está establecido), entonces se usará el valor de la cabecera.

El formato gzip no incluye el tamaño de la ventana en la cabecera, y asume que todos los compresores gzip (por ejemplo, la utilidad gzip o la implementación de gzip.GzipFile de CPython) usan el tamaño de ventana máximo de 32 KiB. Por esta razón, si el parámetro wbits no está establecido, el descompresor usará un tamaño de ventana de 32 KiB (correspondiente a wbits establecido en 15). Esto significa que, para poder descomprimir un stream gzip arbitrario, debes tener al menos esta cantidad de RAM disponible. Si controlas los datos de origen, considera en su lugar usar el formato zlib con un tamaño de ventana más pequeño.

El formato sin procesar no tiene cabecera y, por lo tanto, no incluye ninguna información sobre el tamaño de la ventana. Si wbits no está establecido, entonces se usará por defecto un tamaño de ventana de 256 bytes, que puede no ser lo suficientemente grande para un stream dado. Por lo tanto, se recomienda que siempre establezcas explícitamente wbits si usas el formato sin procesar.

Compresión

Para la compresión, MicroPython usará por defecto un tamaño de ventana de 256 bytes para todos los formatos. Esto proporciona una cantidad razonable de compresión con un uso mínimo de memoria y un tiempo de compresión rápido, y generará una salida que funcionará con cualquier descompresor.