Шаг 250.
Основы языка Python.
Сжатие данных. Сжатие и распаковка по алгоритму LZMA

    На этом шаге мы рассмотрим инструменты для выполнения указанных действий.

    Поддержка формата LZMA появилась в Python 3.3. За нее отвечает модуль lzma.

    Функция open(), открывающая архивный файл для записи или чтения, имеет здесь такой формат:

  open(<Файл>[, mode='rb'][, format=None][, check=-1][, preset=None] [, filters=None]
    [, encoding=None][, errors=None][, newline=None])

    Параметр format задает формат создаваемого или открываемого архивного файла. Здесь доступны следующие значения:

    Параметр check определяет тип проверки целостности архива - его имеет смысл задавать лишь при создании архивного файла. Доступные значения:

    Параметр preset указывает используемый при сжатии или распаковке набор параметров архиватора, фактически - степень сжатия. Доступны числовые значения от 0 (минимальное сжатие и высокая производительность) до 9 (максимальное сжатие и низкая производительность). Этот параметр имеет смысл задавать лишь при создании архивного файла. Значение по умолчанию - lzma.PRESET_DEFAULT, соответствующее числу 6.

    Параметр filters задает набор дополнительных фильтров, используемых при архивировании и распаковке. Отметим, что для формата lzma.FORMAT_RAW фильтр требуется указать обязательно. За описанием процесса создания фильтров обращайтесь к документации по Python.

    Функция open() возвращает объект класса LZMAFile, представляющий созданный или открытый архивный файл.

    Если же мы захотим непосредственно создать объект этого класса, то вызовем его конструктор согласно следующему формату:

  LZMAFile (filename=<Файл> [, mode='rb'][, format=None] [, check=-1]
    [, preset=None][, filters=None])

    Представленный ниже код архивирует строку, сохраняет ее в архив, а потом распаковывает.

>>> import lzma
>>> fn = "test.xz"
>>> s = "Это очень, очень, очень, очень большая строка"
>>> f = lzma.open (fn, mode =  "wt", encoding = "utf-8")
>>> f.write(s)
45
>>> f.close()
>>> f = lzma.LZMAFile (filename = fn)
>>> str (f.read(), encoding = "utf-8")
'Это очень, очень, очень, очень большая строка'
>>> f.close()

    Для сжатия и распаковки данных по частям мы применим классы LZMACompressor и LZMADecompressor. Формат вызова конструктора первого класса таков:

  LZMACompressor([format=lzma.FORMAT_XZ][, check=-1][, preset=None]
    [, filters=None])

    Поддерживаются методы compress (<Данные>) и fiush(), знакомые нам по классу BZ2Compressor.

    Конструктор класса LZMADecompressor имеет следующий формат вызова:

  LZMADecompressor ( [format=lzma.FORMAT_AUTO] [, memlimit=None]
    [, filters=None] )

    Параметр memlimit устанавливает максимальный размер памяти в байтах, который может быть использован архиватором. По умолчанию этот размер не ограничен. Отметим, что в случае задания параметра memlimit, если архиватор не сможет уложиться в отведенный ему объем памяти, будет возбуждено исключение LZMAError, класс которого объявлен в модуле lzrna.

    Этим классом поддерживаются знакомые нам метод decompress(<Данные>) и атрибуты eof и unused_data.

    В качестве примера заархивируем и тут же распакуем документ Microsoft Word. Заодно поэкспериментируем с заданием формата архива и степени сжатия.

import lzma
fn = "doc.lzma"
f1 = open ("Задачи Python.doc", "rb")
f2 = open(fn, "wb")
comp = lzma.LZMACompressor(format = lzma.FORMAT_ALONE, preset = 9)
data = f1.read(1024)
while data:
    f2.write(comp.compress(data))
    data = f1.read(1024)
f2.write(comp.flush())
f2.close()
f1.close()
f1 = open("Задачи Python New.doc", "wb")
f2 = open(fn, "rb")
decomp = lzma.LZMADecompressor()
data = f2.read(1024)
while data:
    f1.write(decomp.decompress(data))
    data = f2.read(1024)
f1.close()
f2.close()
Архив с файлом можно взять здесь.

    В модуле lzma определены функции compress() и decompress() для сжатия и распаковки произвольных данных. Только форматы их вызова несколько другие:

  compress (<Данные>[, format=lzma.FORMAT_XZ] [, check=-1] [, preset=None]
    [, filters=None])
и
  decompress (<Данные> [, format=lzma.FORMAT_AUTO] [, memlimit=None]
    [, filters=None] )	.

    Если в процессе обработки архива LZMA возникнет ошибка, будет возбуждено исключение класса LZMAError. Этот класс объявлен в модуле lzma. Пример обработки таких исключений:

import lzma
try:
    f = lzma.open("test.xz")
except lzma.LZMAError:
    print ("Что-то пошло не так...")

    На следующем шаге мы рассмотрим работу с архивами ZIP.




Предыдущий шаг Содержание Следующий шаг