deflate — compressão e descompressão deflate

Este módulo permite a compressão e descompressão de dados binários com o algoritmo DEFLATE (comumente usado na biblioteca zlib e no arquivador gzip). Adicionado no MicroPython v1.21.

Disponibilidade nas placas suportadas pela OpenMV:

Placa

Descompressão

Compressão

OpenMV Cam N6

Sim

Não

OpenMV AE3

Sim

Sim

OpenMV Cam RT1062

Sim

Sim

OpenMV Cam Pure Thermal

Sim

Não

OpenMV Cam M4

Sim

Não

OpenMV Cam M7

Sim

Não

OpenMV Cam H7

Sim

Não

OpenMV Cam H7 Plus

Sim

Não

Arduino Giga

Sim

Não

Arduino Portenta H7

Sim

Não

Arduino Nicla Vision

Sim

Não

Arduino Nano 33 BLE Sense

Sim

Não

Arduino Nano RP2040 Connect

Sim

Não

Classes

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

Esta classe pode ser usada para encapsular um stream, que é qualquer objeto stream-like como um arquivo, socket ou stream (incluindo io.BytesIO). Ela própria é um stream e implementa os métodos padrão read/readinto/write/close.

O stream deve ser um stream bloqueante. Streams não bloqueantes não são suportados atualmente.

O format pode ser definido como qualquer uma das constantes definidas abaixo, e o padrão é AUTO, que para descompressão detectará automaticamente streams gzip ou zlib, e para compressão gerará um stream bruto (raw).

O parâmetro wbits define o logaritmo na base 2 do tamanho da janela do dicionário DEFLATE. Assim, por exemplo, definir wbits como 10 define o tamanho da janela como 1024 bytes. Os valores válidos vão de 5 a 15 inclusive (correspondendo a tamanhos de janela de 32 a 32k bytes).

Se wbits for definido como 0 (o padrão), então para compressão será usado um tamanho de janela de 256 bytes (como se wbits fosse definido como 8). Para descompressão, depende do formato:

  • RAW usará 256 bytes (correspondendo a wbits definido como 8).

  • ZLIB (ou AUTO com zlib detectado) usará o valor do cabeçalho zlib.

  • GZIP (ou AUTO com gzip detectado) usará 32 kilobytes (correspondendo a wbits definido como 15).

Consulte as notas sobre o tamanho da janela abaixo para mais informações sobre o tamanho da janela e os streams zlib e gzip.

Se close for definido como True, então o stream subjacente será fechado automaticamente quando o stream deflate.DeflateIO for fechado. Isso é útil se você quiser retornar um stream deflate.DeflateIO que encapsula outro stream sem que o chamador precise saber como gerenciar o stream subjacente.

Se a compressão estiver habilitada, uma dada instância de deflate.DeflateIO oferece suporte tanto a leitura quanto a escrita. Por exemplo, um stream bidirecional como um socket pode ser encapsulado, o que permite compressão/descompressão em ambas as direções.

Constantes

As quatro constantes format selecionam o enquadramento aplicado ao redor do fluxo de bits deflate bruto.

deflate.AUTO: int

Para descompressão, detecta automaticamente o formato de entrada inspecionando os primeiros bytes do stream (zlib ou gzip). Para compressão, gera um stream deflate bruto sem cabeçalho ou rodapé (equivalente a RAW).

deflate.RAW: int

Um stream deflate bruto (sem cabeçalho, sem rodapé, sem checksum). Como o stream não contém metadados, o descompressor não pode recuperar o tamanho da janela a partir dos dados, portanto wbits deve ser definido explicitamente ao descomprimir – caso contrário, a janela padrão de 256 bytes pode ser pequena demais.

deflate.ZLIB: int

Um stream deflate encapsulado em zlib conforme definido pela RFC 1950: um cabeçalho de 2 bytes que registra o tamanho da janela, a carga útil deflate e um checksum Adler-32 ao final. Compacto e autodescritivo; bem adequado para uso embarcado.

deflate.GZIP: int

Um stream deflate encapsulado em gzip conforme definido pela RFC 1952: um cabeçalho com metadados opcionais de nome de arquivo/timestamp, a carga útil deflate e um CRC-32 ao final mais o comprimento não comprimido. Este é o formato produzido pela ferramenta de linha de comando gzip e por gzip.GzipFile. O cabeçalho não registra o tamanho da janela, portanto o descompressor deve assumir 32 KiB a menos que wbits seja definido.

Exemplos

Um caso de uso típico para deflate.DeflateIO é ler ou escrever um arquivo comprimido a partir do armazenamento:

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 é um stream, ele pode ser usado, por exemplo, com json.dump() e json.load() (e em qualquer outro lugar onde streams possam ser usados):

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)

Se seus dados de origem não estiverem em formato de stream, você pode usar io.BytesIO para transformá-los em um stream adequado para uso com 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()

Tamanho da janela do deflate

O tamanho da janela limita o quão longe no stream o (des)compressor pode fazer referências. Aumentar o tamanho da janela melhorará a compressão, mas exigirá mais memória e tornará o compressor mais lento.

Se um stream de entrada foi comprimido com um determinado tamanho de janela, então DeflateIO usando um tamanho de janela menor falhará no meio da descompressão com OSError, mas apenas se uma referência retroativa realmente apontar para mais longe do que o tamanho da janela do descompressor. Isso significa que pode ser possível descomprimir com um tamanho de janela menor. Por exemplo, isso seria trivialmente o caso se os dados originais não comprimidos forem mais curtos que o tamanho da janela.

Descompressão

O formato zlib inclui um cabeçalho que especifica o tamanho da janela que foi usado para comprimir os dados. Isso indica o tamanho máximo de janela necessário para descomprimir este stream. Se esse valor do cabeçalho for menor que o valor de wbits especificado (ou se wbits não estiver definido), então o valor do cabeçalho será usado.

O formato gzip não inclui o tamanho da janela no cabeçalho e assume que todos os compressores gzip (por exemplo, o utilitário gzip ou a implementação de gzip.GzipFile do CPython) usam o tamanho máximo de janela de 32kiB. Por essa razão, se o parâmetro wbits não for definido, o descompressor usará um tamanho de janela de 32 kiB (correspondendo a wbits definido como 15). Isso significa que, para conseguir descomprimir um stream gzip arbitrário, você deve ter pelo menos essa quantidade de RAM disponível. Se você controla os dados de origem, considere usar o formato zlib com um tamanho de janela menor.

O formato raw não tem cabeçalho e, portanto, não inclui nenhuma informação sobre o tamanho da janela. Se wbits não for definido, ele assumirá por padrão um tamanho de janela de 256 bytes, que pode não ser grande o suficiente para um determinado stream. Portanto, recomenda-se que você sempre defina wbits explicitamente ao usar o formato raw.

Compressão

Para compressão, o MicroPython assumirá por padrão um tamanho de janela de 256 bytes para todos os formatos. Isso fornece uma quantidade razoável de compressão com uso mínimo de memória e tempo de compressão rápido, e gerará uma saída que funcionará com qualquer descompressor.