Автор оригинала: Doug Hellmann.
Цель:
Чтение и запись файлов gzip.
Модуль gzip
предоставляет файловый интерфейс для файлов GNU zip, используя zlib для сжатия и распаковки данных.
Запись сжатых файлов
Функция уровня модуля open ()
создает экземпляр файлового класса GzipFile
. Предоставляются обычные методы записи и чтения байтов.
gzip_write.py
import gzip import io import os outfilename 'example.txt.gz' with gzip.open(outfilename, 'wb') as output: with io.TextIOWrapper(output, encoding'utf-8') as enc: enc.write('Contents of the example file go here.\n') print(outfilename, 'contains', os.stat(outfilename).st_size, 'bytes') os.system('file -b --mime {}'.format(outfilename))
Чтобы записать данные в сжатый файл, откройте файл в режиме 'wb'
. В этом примере GzipFile
заключен в оболочку TextIOWrapper
из модуля io для кодирования текста Unicode в байты, подходящие для сжатия.
$ python3 gzip_write.py application/x-gzip; example.txt.gz contains 75 bytes
Можно использовать различные степени сжатия, передав аргумент compresslevel
. Допустимые значения от 0 до 9 включительно. Более низкие значения быстрее и приводят к меньшему сжатию. Более высокие значения медленнее и сжимаются сильнее, вплоть до определенного момента.
gzip_compresslevel.py
import gzip import io import os import hashlib def get_hash(data): return hashlib.md5(data).hexdigest() data open('lorem.txt', 'r').read() * 1024 cksum get_hash(data.encode('utf-8')) print('Level Size Checksum') print('----- ---------- ---------------------------------') print('data {:>10} {}'.format(len(data), cksum)) for i in range(0, 10): filename 'compress-level-{}.gz'.format(i) with gzip.open(filename, 'wb', compressleveli) as output: with io.TextIOWrapper(output, encoding'utf-8') as enc: enc.write(data) size os.stat(filename).st_size cksum get_hash(open(filename, 'rb').read()) print('{:>5d} {:>10d} {}'.format(i, size, cksum))
Центральный столбец чисел на выходе показывает размер в байтах файлов, созданных при сжатии входных данных. Для этих входных данных более высокие значения сжатия не обязательно окупаются меньшим объемом памяти. Результаты будут отличаться в зависимости от входных данных.
$ python3 gzip_compresslevel.py Level Size Checksum ----- ---------- --------------------------------- data 754688 e4c0f9433723971563f08a458715119c 0 754793 ced7189c324eb73a8388492a9024d391 1 9846 5356d357f23e0d5b6d85e920929f0e43 2 8267 8ce46bce238edc095e47e941cebad93d 3 8227 91662517459db94a744671a6b4295b67 4 4167 ad304e3aec585640de9f14306fb32083 5 4167 4381a5d6dff4dd2746387f20411dcfcd 6 4167 ef3a05112ea382abb53bc4a5bee3a52a 7 4167 4723a253d1dc8ddecd4ff7b7adf0bc0b 8 4167 0e1aeba7bdc39f0007039f130d9a28b2 9 4167 eccf47c4c4f1cca3274e57a1b9b9ddd2
Экземпляр GzipFile
также включает метод writelines ()
, который можно использовать для записи последовательности строк.
gzip_writelines.py
import gzip import io import itertools import os with gzip.open('example_lines.txt.gz', 'wb') as output: with io.TextIOWrapper(output, encoding'utf-8') as enc: enc.writelines( itertools.repeat('The same line, over and over.\n', 10) ) os.system('gzcat example_lines.txt.gz')
Как и в случае с обычным файлом, строки ввода должны включать новую строку
$ python3 gzip_writelines.py The same line, over and over. The same line, over and over. The same line, over and over. The same line, over and over. The same line, over and over. The same line, over and over. The same line, over and over. The same line, over and over. The same line, over and over. The same line, over and over.
Чтение сжатых данных
Чтобы прочитать данные из ранее сжатых файлов, откройте файл в двоичном режиме чтения ( 'rb'
), чтобы не выполнялось текстовое преобразование окончаний строк или декодирование Unicode.
gzip_read.py
import gzip import io with gzip.open('example.txt.gz', 'rb') as input_file: with io.TextIOWrapper(input_file, encoding'utf-8') as dec: print(dec.read())
В этом примере выполняется чтение файла, записанного gzip_write.py
из предыдущего раздела, с использованием TextIOWrapper
для декодирования текста после его распаковки.
$ python3 gzip_read.py Contents of the example file go here.
Во время чтения файла также можно искать и читать
gzip_seek.py
import gzip with gzip.open('example.txt.gz', 'rb') as input_file: print('Entire file:') all_data input_file.read() print(all_data) expected all_data[5:15] # rewind to beginning input_file.seek(0) # move ahead 5 bytes input_file.seek(5) print('Starting at position 5 for 10 bytes:') partial input_file.read(10) print(partial) print() print(expected partial)
Положение seek ()
относится к несжатым данным, поэтому вызывающий
$ python3 gzip_seek.py Entire file: b'Contents of the example file go here.\n' Starting at position 5 for 10 bytes: b'nts of the' True
Работа с потоками
Класс GzipFile
можно использовать для упаковки других типов потоков данных, чтобы они также могли использовать сжатие. Это полезно, когда данные передаются через сокет или существующий (уже открытый) файл.
gzip_BytesIO.py
import gzip from io import BytesIO import binascii uncompressed_data b'The same line, over and over.\n' * 10 print('UNCOMPRESSED:', len(uncompressed_data)) print(uncompressed_data) buf BytesIO() with gzip.GzipFile(mode'wb', fileobjbuf) as f: f.write(uncompressed_data) compressed_data buf.getvalue() print('COMPRESSED:', len(compressed_data)) print(binascii.hexlify(compressed_data)) inbuffer BytesIO(compressed_data) with gzip.GzipFile(mode'rb', fileobjinbuffer) as f: reread_data f.read(len(uncompressed_data)) print('\nREREAD:', len(reread_data)) print(reread_data)
Одним из преимуществ использования GzipFile
над zlib является то, что он поддерживает файловый API. Однако при повторном чтении ранее сжатых данных явная длина передается в read ()
. Отсутствие длины привело к ошибке CRC, возможно потому, что BytesIO
вернул пустую строку перед сообщением EOF. При работе с потоками сжатых данных либо используйте префикс данных с целым числом, представляющим фактический объем данных для чтения, либо используйте API инкрементной декомпрессии.
$ python3 gzip_BytesIO.py UNCOMPRESSED: 300 b'The same line, over and over.\nThe same line, over and over.\nT he same line, over and over.\nThe same line, over and over.\nThe same line, over and over.\nThe same line, over and over.\nThe sam e line, over and over.\nThe same line, over and over.\nThe same l ine, over and over.\nThe same line, over and over.\n' COMPRESSED: 51 b'1f8b080022caae5a02ff0bc94855284ecc4d55c8c9cc4bd551c82f4b2d5248c c4b0133f4b8424665916401d3e717802c010000' REREAD: 300 b'The same line, over and over.\nThe same line, over and over.\nT he same line, over and over.\nThe same line, over and over.\nThe same line, over and over.\nThe same line, over and over.\nThe sam e line, over and over.\nThe same line, over and over.\nThe same l ine, over and over.\nThe same line, over and over.\n'
Смотрите также
- стандартная библиотечная документация для gzip
- zlib – модуль
zlib
– это интерфейс нижнего уровня для сжатия gzip. - zipfile – модуль
zipfile
предоставляет доступ к ZIP-архивам. - bz2