deflate — стиснення та розпакування deflate¶
Цей модуль дозволяє стискати та розпаковувати двійкові дані за допомогою алгоритму DEFLATE (широко використовується у бібліотеці zlib та архіваторі gzip). Додано в MicroPython v1.21.
Доступність на платах, підтримуваних OpenMV:
Плата |
Розпакування |
Стиснення |
|---|---|---|
OpenMV Cam N6 |
Так |
Ні |
OpenMV AE3 |
Так |
Так |
OpenMV Cam RT1062 |
Так |
Так |
OpenMV Cam Pure Thermal |
Так |
Ні |
OpenMV Cam M4 |
Так |
Ні |
OpenMV Cam M7 |
Так |
Ні |
OpenMV Cam H7 |
Так |
Ні |
OpenMV Cam H7 Plus |
Так |
Ні |
Arduino Giga |
Так |
Ні |
Arduino Portenta H7 |
Так |
Ні |
Arduino Nicla Vision |
Так |
Ні |
Arduino Nano 33 BLE Sense |
Так |
Ні |
Arduino Nano RP2040 Connect |
Так |
Ні |
Класи¶
- class deflate.DeflateIO(stream: Any, format: int = AUTO, wbits: int = 0, close: bool = False, /)¶
Цей клас дозволяє обгортати stream — будь-який об’єкт, подібний до потоку, наприклад файл, сокет або потік (зокрема
io.BytesIO). Сам є потоком і реалізує стандартні методи read/readinto/write/close.stream має бути блокуючим потоком. Неблокуючі потоки наразі не підтримуються.
Параметр format може приймати будь-яке зі значень констант, визначених нижче, і за замовчуванням дорівнює
AUTO: при розпакуванні автоматично визначає формат gzip або zlib, а при стисненні генерує «сирий» потік.Параметр wbits задає двійковий логарифм розміру вікна словника DEFLATE. Наприклад, встановлення wbits у
10задає розмір вікна 1024 байти. Допустимі значення від5до15включно (відповідають розмірам вікна від 32 до 32768 байт).Якщо wbits встановлено у
0(за замовчуванням), то при стисненні буде використано вікно розміром 256 байт (як ніби wbits встановлено у 8). При розпакуванні поведінка залежить від формату:RAWвикористовуватиме 256 байт (що відповідає wbits = 8).ZLIB(абоAUTOз виявленим zlib) використовуватиме значення із заголовка zlib.GZIP(абоAUTOз виявленим gzip) використовуватиме 32 кілобайти (що відповідає wbits = 15).
Докладніше про розмір вікна, zlib та gzip-потоки — у примітці window size нижче.
Якщо close встановлено у
True, базовий потік буде автоматично закрито при закритті потокуdeflate.DeflateIO. Це зручно, коли потрібно повернути потікdeflate.DeflateIO, що обгортає інший потік, і не навантажувати виклику необхідністю керувати базовим потоком.Якщо стиснення увімкнено, конкретний екземпляр
deflate.DeflateIOпідтримує як читання, так і запис. Наприклад, можна обгорнути двонаправлений потік, такий як сокет, що дозволяє виконувати стиснення/розпакування в обох напрямках.
Константи¶
Чотири константи format визначають обрамлення навколо «сирого» бітового потоку deflate.
- deflate.AUTO: int¶
При розпакуванні автоматично визначає вхідний формат, аналізуючи перші байти потоку (zlib або gzip). При стисненні генерує «сирий» потік deflate без заголовка та трейлера (еквівалентно
RAW).
- deflate.RAW: int¶
«Сирий» потік deflate (без заголовка, трейлера та контрольної суми). Оскільки потік не містить метаданих, декомпресор не може відновити розмір вікна з даних, тому при розпакуванні wbits слід задавати явно — інакше вікно за замовчуванням 256 байт може бути замалим.
- deflate.ZLIB: int¶
Потік deflate у форматі zlib, як визначено RFC 1950: 2-байтний заголовок із записом розміру вікна, корисне навантаження deflate та кінцева контрольна сума Adler-32. Компактний і самоописовий; добре підходить для вбудованих систем.
- deflate.GZIP: int¶
Потік deflate у форматі gzip, як визначено RFC 1952: заголовок із необов’язковими метаданими (ім’я файлу/мітка часу), корисне навантаження deflate та кінцеві CRC-32 і нестиснена довжина. Це формат, який генерує утиліта
gzipтаgzip.GzipFile. Заголовок не містить розміру вікна, тому декомпресор повинен припускати 32 КіБ, якщо wbits не задано.
Приклади¶
Типовий випадок використання deflate.DeflateIO — читання або запис стисненого файлу зі сховища:
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.
Оскільки deflate.DeflateIO є потоком, його можна використовувати, наприклад, з json.dump() та json.load() (і в будь-яких інших місцях, де використовуються потоки):
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)
Якщо вихідні дані не є потоком, можна скористатися io.BytesIO, щоб перетворити їх на потік, придатний для використання з 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()
Розмір вікна Deflate¶
Розмір вікна обмежує, наскільки далеко назад у потоці (де)компресор може шукати посилання. Збільшення розміру вікна покращує стиснення, але потребує більше пам’яті та сповільнює компресор.
Якщо вхідний потік було стиснено з певним розміром вікна, а DeflateIO використовує менший розмір вікна, розпакування може завершитися невдачею посередині з OSError, але лише якщо зворотне посилання справді виходить за межі вікна декомпресора. Це означає, що розпакування з меншим вікном може бути можливим. Наприклад, якщо вихідні нестиснені дані коротші за розмір вікна, це буде виконано без проблем.
Розпакування¶
Формат zlib містить заголовок, у якому вказано розмір вікна, що використовувався при стисненні. Це вказує на максимальний розмір вікна, необхідний для розпакування потоку. Якщо це значення з заголовка менше за вказане wbits (або якщо wbits не задано), буде використано значення з заголовка.
Формат gzip не включає розмір вікна у заголовок і передбачає, що всі компресори gzip (наприклад, утиліта gzip або реалізація gzip.GzipFile в CPython) використовують максимальний розмір вікна 32 КіБ. З цієї причини, якщо параметр wbits не задано, декомпресор використовуватиме вікно 32 КіБ (що відповідає wbits = 15). Це означає, що для розпакування довільного gzip-потоку необхідно мати щонайменше стільки оперативної пам’яті. Якщо ви контролюєте джерело даних, розгляньте використання формату zlib із меншим розміром вікна.
Формат raw не містить заголовка і тому не включає жодної інформації про розмір вікна. Якщо wbits не задано, за замовчуванням буде використано вікно 256 байт, якого може бути недостатньо для конкретного потоку. Тому рекомендується завжди явно задавати wbits при використанні raw-формату.
Стиснення¶
При стисненні MicroPython за замовчуванням використовує вікно 256 байт для всіх форматів. Це забезпечує розумний ступінь стиснення при мінімальному використанні пам’яті та швидкому часі стиснення, і генерує вихідні дані, сумісні з будь-яким декомпресором.