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 до 32k байт).Если wbits установлен в
0(по умолчанию), то для сжатия будет использоваться размер окна 256 байт (как если бы wbits был установлен в 8). Для распаковки это зависит от формата:RAWбудет использовать 256 байт (соответствует wbits, установленному в 8).ZLIB(илиAUTOс обнаруженным zlib) будет использовать значение из заголовка zlib.GZIP(илиAUTOс обнаруженным gzip) будет использовать 32 килобайта (соответствует wbits, установленному в 15).
Дополнительную информацию о размере окна, потоках zlib и gzip смотрите в примечаниях о размере окна ниже.
Если 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 KiB, если 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 KiB. По этой причине, если параметр wbits не задан, распаковщик будет использовать размер окна 32 KiB (соответствует wbits, установленному в 15). Это означает, что для возможности распаковки произвольного потока gzip у вас должно быть доступно как минимум столько ОЗУ. Если вы контролируете исходные данные, рассмотрите вместо этого использование формата zlib с меньшим размером окна.
Необработанный формат не имеет заголовка и поэтому не включает никакой информации о размере окна. Если wbits не задан, то по умолчанию будет использоваться размер окна 256 байт, который может оказаться недостаточно большим для данного потока. Поэтому рекомендуется всегда явно задавать wbits при использовании необработанного формата.
Сжатие¶
Для сжатия MicroPython по умолчанию использует размер окна 256 байт для всех форматов. Это обеспечивает разумную степень сжатия при минимальном использовании памяти и быстром времени сжатия, а также генерирует вывод, который будет работать с любым распаковщиком.