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

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

    С архивными файлами любой пользователь сталкивается постоянно. В них распространяются дистрибутивы программ, документы, изображения, всевозможные служебные данные, в том числе и дополнительные библиотеки Python.

    Неудивительно, что рассматриваемый нами язык программирования включает в состав стандартной библиотеки развитые средства для упаковки и распаковки как целых файлов, так и произвольных данных.

Сжатие и распаковка по алгоритму GZIP

    Для сжатия и распаковки файлов и данных по популярному алгоритму GZIP используются средства, определенные в модуле gzip.

    Прежде всего, это функция open(). Формат ее вызова таков:

 open (<Файл>[, mode='rb'][, compresslevel=9][, encoding= None]
    [, errors= None][, newline= None])

    Первым параметром указывается либо путь к открываемому архивному файлу, либо представляющий его файловый объект. Второй параметр задает режим открытия файла (об этом подробно рассказано на 160 шаге): файл может быть открыт как в текстовом, так и в двоичном режиме. Третий параметр указывает степень сжатия архива в виде целого числа от 1 (минимальная степень, но максимальная скорость сжатия) до 9 (максимальная степень и минимальная скорость сжатия), также может быть задано значение 0 (отсутствие сжатия). Остальные параметры имеют смысл лишь при открытии файла в текстовом режиме и рассмотрены на том же шаге.

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

    Функция open() возвращает объект класса GzipFile, представляющий открытый архивный файл. Этот класс поддерживает все атрибуты и методы, описанные, начиная с 161 шага, за исключением метода truncate(). При этом все записываемые в такой файл данные будут автоматически архивироваться, а считываемые из него - распаковываться. Для примера давайте создадим архивный GZIP-файл, сохраним в него строку, после чего откроем тот же файл и прочитаем его содержимое.

>>> import gzip
>>> fn =  "test.gz"
>>> s = "Это очень, очень, очень, очень большая строка"
>>> f = gzip.open (fn, mode =  "wt", encoding = "utf-8")
>>> f.write(s)
45
>>> f.close()
>>> f = gzip.open (fn, mode = "rt", encoding = "utf-8")
>>> print (f.read())
Это очень, очень, очень, очень большая строка
>>> f.close()

    Вместо функции open() можно непосредственно создать объект класса GzipFile. Его конструктор имеет следующий формат вызова:

  GzipFile ( [filename= None] [, mode='rb'][, compresslevel=9]
    [, fileobj=None] [, mtime=None])

    Можно задать либо путь к файлу в параметре filename, либо файловый объект в параметре fiieobj. Если задано и то, и другое, имя файла будет включено в заголовок создаваемого GZIP-файла.

    Параметр mtime указывает значение времени, которое будет добавлено в заголовок создаваемого архивного файла, как того требует формат GZIP. Это значение может быть получено вызовом функции time() из модуля time или сформировано иным образом. Если параметр не указан, будет использовано текущее время.

    Отметим, что архивный файл в этом случае всегда открывается в двоичном режиме, и открыть его в текстовом режиме нельзя, даже если указать текстовый режим открытия.

    Давайте сохраним в архиве графическое изображение, после чего распакуем его. Для создания архива используем функцию open(), а для распаковки - класс GzipFile.

>>> import gzip
>>> fn = "image.gz"
>>> f1 = open ("cartitle.jpg", "rb")
>>> f2 = gzip.open(fn, "wb")
>>> f2.write(f1.read())
45197
>>> f2.close()
>>> f1.close()
>>> f1 = open("cartitle_new.jpg", "wb")
>>> f2 = gzip.GzipFile (filename = fn)
>>> f1.write (f2.read())
45197
>>> f1.close()
>>> f2.close()

    В модуле gzip присутствуют также две функции, позволяющие сжимать и распаковывать произвольные двоичные данные без сохранения их в файл. Функция compress (<Значение>[, compresslevel=9]) выполняет сжатие значения и возвращает получившийся в результате массив байтов типа bytes:

>>> import gzip
>>> s = b"This is a very, very, very, very big string"
>>> gzip.compress (s)
b'\x1f\x8b\x08\x00\x84h4\\\x02\xff\x0b\xc9\xc8,V\x00\xa2D\x85\xb2\xd4\xa2J\x1d\x0cR!)3]
\xa1\xb8\xa4(3/\x1d\x00\xbaZ)I+\x00\x00\x00'

    А функция decompress (<Значение>) выполняет распаковку сжатых данных и возвращает получившийся результат:

>>> b = b'\x1f\x8b\x08\x00\x84h4\\\x02\xff\x0b\xc9\xc8,V\x00\xa2D\x85\xb2\xd4\xa2J
\x1d\x0cR!)3]\xa1\xb8\xa4(3/\x1d\x00\xbaZ)I+\x00\x00\x00'
>>> gzip.decompress(b)
b'This is a very, very, very, very big string'

    На следующем шаге мы рассмотрим сжатие и распаковку по алгоритму BZIP2.




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