deflate — kompresja i dekompresja deflate¶
Ten moduł umożliwia kompresję i dekompresję danych binarnych za pomocą algorytmu DEFLATE (powszechnie używanego w bibliotece zlib oraz archiwizatorze gzip). Dodany w MicroPython v1.21.
Dostępność na płytkach obsługiwanych przez OpenMV:
Płytka |
Dekompresja |
Kompresja |
|---|---|---|
OpenMV Cam N6 |
Tak |
Nie |
OpenMV AE3 |
Tak |
Tak |
OpenMV Cam RT1062 |
Tak |
Tak |
OpenMV Cam Pure Thermal |
Tak |
Nie |
OpenMV Cam M4 |
Tak |
Nie |
OpenMV Cam M7 |
Tak |
Nie |
OpenMV Cam H7 |
Tak |
Nie |
OpenMV Cam H7 Plus |
Tak |
Nie |
Arduino Giga |
Tak |
Nie |
Arduino Portenta H7 |
Tak |
Nie |
Arduino Nicla Vision |
Tak |
Nie |
Arduino Nano 33 BLE Sense |
Tak |
Nie |
Arduino Nano RP2040 Connect |
Tak |
Nie |
Klasy¶
- class deflate.DeflateIO(stream: Any, format: int = AUTO, wbits: int = 0, close: bool = False, /)¶
Tej klasy można użyć do opakowania stream, czyli dowolnego obiektu przypominającego strumień, takiego jak plik, gniazdo lub strumień (w tym
io.BytesIO). Sama jest strumieniem i implementuje standardowe metody read/readinto/write/close.stream musi być strumieniem blokującym. Strumienie nieblokujące nie są obecnie obsługiwane.
format można ustawić na dowolną ze stałych zdefiniowanych poniżej; domyślnie ma wartość
AUTO, która przy dekompresji automatycznie wykrywa strumienie gzip lub zlib, a przy kompresji generuje strumień surowy.Parametr wbits ustawia logarytm o podstawie 2 z rozmiaru okna słownika DEFLATE. Na przykład ustawienie wbits na
10ustawia rozmiar okna na 1024 bajty. Prawidłowe wartości to od5do15włącznie (odpowiadające rozmiarom okna od 32 do 32k bajtów).Jeśli wbits zostanie ustawione na
0(wartość domyślna), to przy kompresji zostanie użyty rozmiar okna 256 bajtów (tak jakby wbits ustawiono na 8). Przy dekompresji zależy to od formatu:RAWużyje 256 bajtów (odpowiadających wbits ustawionemu na 8).ZLIB(lubAUTOz wykrytym zlib) użyje wartości z nagłówka zlib.GZIP(lubAUTOz wykrytym gzip) użyje 32 kilobajtów (odpowiadających wbits ustawionemu na 15).
Więcej informacji o rozmiarze okna oraz strumieniach zlib i gzip można znaleźć w uwagach o rozmiarze okna poniżej.
Jeśli close zostanie ustawione na
True, to bazowy strumień zostanie automatycznie zamknięty wraz z zamknięciem strumieniadeflate.DeflateIO. Jest to przydatne, gdy chcesz zwrócić strumieńdeflate.DeflateIOopakowujący inny strumień, tak aby wywołujący nie musiał zajmować się zarządzaniem bazowym strumieniem.Jeśli kompresja jest włączona, dana instancja
deflate.DeflateIOobsługuje zarówno odczyt, jak i zapis. Na przykład można opakować strumień dwukierunkowy, taki jak gniazdo, co umożliwia kompresję/dekompresję w obu kierunkach.
Stałe¶
Cztery stałe format wybierają ramkowanie nakładane wokół surowego strumienia bitów deflate.
- deflate.AUTO: int¶
Przy dekompresji automatycznie wykrywa format danych wejściowych, sprawdzając pierwsze bajty strumienia (zlib lub gzip). Przy kompresji generuje surowy strumień deflate bez nagłówka i stopki (równoważnie do
RAW).
- deflate.RAW: int¶
Surowy strumień deflate (bez nagłówka, bez stopki, bez sumy kontrolnej). Ponieważ strumień nie zawiera żadnych metadanych, dekompresor nie może odzyskać rozmiaru okna z danych, więc przy dekompresji należy jawnie ustawić wbits – w przeciwnym razie domyślne okno 256 bajtów może być zbyt małe.
- deflate.ZLIB: int¶
Strumień deflate opakowany w zlib, zgodny z definicją RFC 1950: 2-bajtowy nagłówek zapisujący rozmiar okna, ładunek deflate oraz końcowa suma kontrolna Adler-32. Zwarty i samoopisujący się; dobrze nadaje się do zastosowań wbudowanych.
- deflate.GZIP: int¶
Strumień deflate opakowany w gzip, zgodny z definicją RFC 1952: nagłówek z opcjonalnymi metadanymi nazwy pliku/znacznika czasu, ładunek deflate oraz końcowa suma kontrolna CRC-32 wraz z długością nieskompresowaną. Jest to format generowany przez narzędzie wiersza poleceń
gziporaz przezgzip.GzipFile. Nagłówek nie zapisuje rozmiaru okna, więc dekompresor musi przyjąć 32 KiB, chyba że ustawiono wbits.
Przykłady¶
Typowym przypadkiem użycia deflate.DeflateIO jest odczyt lub zapis skompresowanego pliku z pamięci masowej:
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.
Ponieważ deflate.DeflateIO jest strumieniem, można go używać na przykład z json.dump() i json.load() (oraz w każdym innym miejscu, gdzie można używać strumieni):
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)
Jeśli Twoje dane źródłowe nie są w formacie strumienia, możesz użyć io.BytesIO, aby zamienić je w strumień odpowiedni do użycia z 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()
Rozmiar okna deflate¶
Rozmiar okna ogranicza, jak daleko wstecz w strumieniu (de)kompresor może się odwoływać. Zwiększenie rozmiaru okna poprawi kompresję, ale będzie wymagało więcej pamięci i spowolni kompresor.
Jeśli strumień wejściowy został skompresowany z danym rozmiarem okna, to DeflateIO używające mniejszego rozmiaru okna zakończy się niepowodzeniem w trakcie dekompresji z błędem OSError, ale tylko wtedy, gdy odwołanie wsteczne faktycznie sięga dalej niż rozmiar okna dekompresora. Oznacza to, że może być możliwa dekompresja przy mniejszym rozmiarze okna. Na przykład będzie tak w sposób oczywisty, gdy oryginalne nieskompresowane dane są krótsze niż rozmiar okna.
Dekompresja¶
Format zlib zawiera nagłówek określający rozmiar okna użyty do kompresji danych. Wskazuje to maksymalny rozmiar okna wymagany do dekompresji tego strumienia. Jeśli ta wartość z nagłówka jest mniejsza niż podana wartość wbits (lub jeśli wbits nie jest ustawione), to zostanie użyta wartość z nagłówka.
Format gzip nie zawiera rozmiaru okna w nagłówku i zakłada, że wszystkie kompresory gzip (np. narzędzie gzip lub implementacja gzip.GzipFile w CPythonie) używają maksymalnego rozmiaru okna 32kiB. Z tego powodu, jeśli parametr wbits nie jest ustawiony, dekompresor użyje rozmiaru okna 32 kiB (odpowiadającego wbits ustawionemu na 15). Oznacza to, że aby móc zdekompresować dowolny strumień gzip, musisz mieć dostępną co najmniej taką ilość pamięci RAM. Jeśli kontrolujesz dane źródłowe, rozważ zamiast tego użycie formatu zlib z mniejszym rozmiarem okna.
Format surowy nie ma nagłówka i dlatego nie zawiera żadnych informacji o rozmiarze okna. Jeśli wbits nie jest ustawione, to domyślnie przyjmie rozmiar okna 256 bajtów, który może nie być wystarczająco duży dla danego strumienia. Dlatego zaleca się, abyś przy używaniu formatu surowego zawsze jawnie ustawiał wbits.
Kompresja¶
Przy kompresji MicroPython domyślnie przyjmie rozmiar okna 256 bajtów dla wszystkich formatów. Zapewnia to rozsądny poziom kompresji przy minimalnym zużyciu pamięci i krótkim czasie kompresji oraz generuje wynik, który będzie działał z dowolnym dekompresorem.