Как сжать файлы python
Модуль gzip Python обеспечивает очень простой способ сжатия и распаковки файлов и работает аналогично программам GNU gzip и gunzip.
В этом уроке мы изучим, какие классы присутствуют в этом модуле, который позволяет нам выполнять упомянутые операции вместе с дополнительными функциями, которые он предоставляет.
Этот модуль предоставляет нам класс Gzip, который содержит некоторые удобные функции, такие как open(), compress() и decopress().
Преимущество класса Gzip заключается в том, что он читает и записывает файлы gzip и автоматически сжимает и распаковывает их, так что в программе они выглядят так же, как обычные объекты File.
Важно помнить, что другие форматы, поддерживаемые программами gzip и gunzip, не поддерживаются этим модулем.
Использование модуля
Теперь мы начнем использовать упомянутые функции для выполнения операций сжатия и распаковки.
Запись сжатых файлов с помощью open()
Мы начнем с функции open(), которая создает экземпляр GzipFile и открывает файл в режиме wb для записи в сжатый файл:
Посмотрим на результат этой программы:
Чтобы записать в сжатый файл, мы сначала открыли его в режиме wb и обернули экземпляр GzipFile с помощью TextIOWrapper из модуля io для кодирования текста Unicode в байты, которые подходят для сжатия.
Запись нескольких строк в сжатый файл
На этот раз мы будем использовать почти тот же сценарий, что и выше, но напишем в него несколько строк. Давайте посмотрим на код, как этого можно добиться:
Посмотрим на результат этой программы:
Чтение сжатых данных
Теперь, когда мы закончили процесс записи файла, мы также можем читать данные из сжатого файла. Теперь мы будем использовать другой файловый режим – rb, режим чтения.
Посмотрим на результат этой программы:
Обратите внимание, что мы не сделали здесь ничего особенного с Gzip, кроме передачи ему другого файлового режима. Процесс чтения выполняется TextIOWrapper, который использует объект File, как объект, предоставляемый модулем gzip.
Чтение потоков
Еще одно большое преимущество модуля gzip заключается в том, что его можно использовать для обертывания других типов потоков, чтобы они могли также использовать сжатие. Это чрезвычайно полезно, когда вы хотите передавать большой объем данных через веб-сокеты.
Давайте посмотрим, как мы можем сжимать и распаковывать данные потока:
Посмотрим на результат этой программы:
Обратите внимание, что при записи нам не нужно было указывать параметры длины. Но этого не произошло, когда мы перечитали данные. Нам пришлось явно передать длину функции read().
Если вы пользовались компьютером хоть немного, то возможно вам встречались файлы с расширением .zip. Это специальные файлы в которые могут содержать в сжатом состоянии большое количество других файлов, директорий и поддиректорий. Это делает их очень удобными для передачи данных через интернет. А знаете ли вы, что вы можете использовать Python для сжатия и распаковки архивов?
В этом уроке вы научитесь как использовать библиотеку zipfile, чтобы извлекать или упаковывать один или сразу несколько файлов в архив.
Сжатие Одиночных Файлов
Это очень просто, и потребует написать совсем немного кода. Начинаем с того, что импортируем модуль zipfile и затем инициируем объект ZipFile с возможностью записи, указав это с помощью второго параметра 'w'. Первый параметр, это путь к файлу. Вот код, который нам нужен:
Пожалуйста, обратите внимание, что я буду указывать путь во всех фрагментах кода в формате для Windows; если вы работаете на Linux или Mac, вам нужно будет внести соответствующие изменения.
Вы можете указать различные методы сжатия, что бы заархивировать файл. В Python версии 3.3 были добавлены новые методы BZIP2 и LZMA , а также некоторые другие инструменты, которые не поддерживают эти два метода сжатия. По этой причине безопасно использовать метод DEFLATED . Но вам все же стоит попробовать эти методы, что бы увидеть разницу в размерах сжатого файла.
Сжатие Нескольких Файлов
Это будет чуть сложнее, так как вы должны выполнить итерационный процесс для всех файлов. Код показанный ниже должен заархивировать все файлы в директории с расширением pdf.
На этот раз нам необходимо импортировать модуль os и использовать метод walk() , чтобы пробежаться про всем файлам и поддиректориям в нашей основной директории. Я архивирую только файлы с расширением pdf. Вы так же можете создавать различные архивные файлы для разных форматов файлов используя оператор if .
Если вы не хотите, сохранить структуру каталога, вы можете положить все файлы вместе, используя следующую строку:
Метод write() допускает три параметра. Первый параметр - это имя нашего файла, который мы хотим сжать. Второй параметр не обязательный, он позволяет вам указать другое имя для файла архива. Если ничего не указано, будет использоваться имя архивируемого файла.
Извлечение Всех Файлов
Вы можете использовать метод extractall() для извлечения всех файлов и папок из zip-файла в текущую рабочую директорию. Вы можете также указать имя папки в extractall() для извлечения всех файлов и директорий в заданный каталог. Если директория, которую вы указали не существует, метод сам создаст новую. Вот код, который вы можете использовать для извлечения файлов:
Если вы хотите распаковать несколько файлов, вам необходимо подставить имена этих файлов в виде списка.
Извлечение Единичных Файлов
Это подобно извлечению нескольких файлов. Одно отличие состоит в том, что на этот раз, вам необходимо сначала подставить имя файла и затем, путь для извлечения. Кроме того необходимо использовать метод extract() вместо extractall() . Вот фрагмент кода для извлечения отдельных файлов.
Чтение Архивов
Рассмотрим сценарий, где вам нужно узнать содержит ли zip-архив конкретный файл. До этого момента, вы могли это сделать только распаковав весь архив. Аналогичным образом, может потребоваться извлечь только те файлы, которые больше, определенного размера. Модуль Zipfile позволяет нам узнать содержимое архива без его распаковки.
Применение метода namelist() к объекту ZipFile вернет список всех элементов архива по имени. Чтобы получить информацию о конкретном файле в архиве, можно использовать для ZipFile метод getinfo() . Это даст вам доступ к информации об этом файле, такой как, размер сжатого и несжатого файла или информацию о времени его последнего изменения. Мы вернемся к этому позже.
Вызов метода getinfo() для каждого файла может быть утомительным процессом, когда этих файлов много. В этом случае можно использовать метод infolist() для возврата списка всех элементов, содержащихся в объекте ZipInf. Порядок этих объектов в списке такой же, как и в zip-файлах.
Вы можете также непосредственно прочитать содержимое определенного файла из архива, с помощью метода read(file) , где file — имя файла, который вы хотите прочесть. Для этого, архив должен быть открыт в режиме чтения или в режиме добавления.
Чтобы получить размер конкретного сжатого файла из архива, нужно использовать атрибут compress_size . Аналогично чтобы узнать, несжатый размер, можно использовать атрибут file_size .
Следующий код использует свойства и методы, которые мы только что обсудили, чтобы извлечь только те файлы, размер которых менее 1 МБ.
Чтобы узнать время и дату последнего изменения определенного файла из архива, можно использовать атрибут date_time . Это возвращает кортеж из шести величин. Этими величинами будут год, месяц, день месяца, часы, минуты и секунды, в установленном порядке. Год будет всегда больше или равен 1980 года и часы, минуты и секунды от нуля.
Информация об оригинальном размере файла и размере сжатого файла может помочь вам увидеть, принесло ли архивирование пользу. Я думаю, это может быть так же использовано и в других случаях.
Заключительные мысли
Как видно из этого урока, использование модуля zipfile, позволяет вам гибко использовать сжатие файлов. Вы можете архивировать файлы в директории в различные архивы в зависимости от их типа, имени и размера. Вы так же можете решать оставлять вам структуру директории или нет. Аналогично при извлечении файлов, вы можете извлекать их куда вам нужно, на основе собственных критериев, таких как размер, и т.д.
Если честно, мне было очень интересно архивировать и извлекать файлы пока я писал свой код. Я надеюсь урок был вам полезен, и если у вас остались какие-то вопросы, пишите их пожалуйста в комментариях.
Если вы давно пользуетесь компьютером, то наверняка сталкивались с файлами с расширением zip. Это специальные файлы, которые содержат сжатое содержимое многих других файлов, папок и подпапок, что делает их очень полезными для передачи файлов через Интернет. Знаете ли вы, что для сжатия и извлечения файлов можно использовать Python?
В этом уроке я покажу вам, как использовать модуль zipfile в Python для извлечения или сжатия как отдельных файлов, так и нескольких одновременно.
Сжатие отдельных файлов
При архивации файлов можно определить различные методы сжатия. Новые методы BZIP2 и LZMA были добавлены в Python в версии 3.3, но есть инструменты, которые не поддерживают эти два метода. Поэтому безопаснее всего использовать метод DEFLATED.
Сжатие нескольких файлов
Это немного сложнее, так как необходимо перебрать все файлы. Следующий код должен сжать все pdf-файлы в заданной папке:
Мы импортировали модуль os и использовали его метод walk() для проверки всех файлов и подпапок внутри нашей исходной директории. Я сжимаю только файлы pdf в каталоге. Вы можете создавать различные архивы для каждого формата с помощью операторов if.
Если вы не хотите сохранять структуру каталогов, вы можете собрать все файлы вместе с помощью следующей строки:
Распаковка всех файлов
Вы можете использовать метод extractall() для извлечения всех файлов и папок из zip-архива в текущий рабочий каталог. Вы также можете передавать имя папки в extractall() для извлечения всех файлов и папок в определенном каталоге. Если переданная вам папка не существует, этот метод создаст новую. Вот код, который вы можете использовать для извлечения файлов:
Распаковка отдельных файлов
Это очень похоже на извлечение нескольких файлов. Единственное отличие заключается в том, что сначала вы должны передать имя файла, а затем путь для дальнейшего извлечения. Кроме того, вы должны использовать метод extract() вместо extractall(). Вот базовый фрагмент кода для извлечения отдельных файлов.
Сохраните статью в социальных сетях, чтобы не потерять.Похожие записи
Сравнивать даты в Python очень просто. Для этого достаточно использовать операторы сравнения. В этой статье…
JSON позволяет быстро и просто работать с несколькими данными: в различных приложениях и языках программирования.…
Если вы какое-то время пользовались компьютерами, вы, вероятно, сталкивались с файлами с расширением .zip . Это специальные файлы, которые могут содержать сжатый контент многих других файлов, папок и подпапок. Это делает их довольно полезными для передачи файлов через Интернет. Знаете ли вы, что вы можете использовать Python для сжатия или извлечения файлов?
Из этого туториала вы узнаете, как использовать модуль zipfile в Python для извлечения или сжатия отдельных или нескольких файлов одновременно.
Сжатие отдельных файлов
Обратите внимание, что я буду указывать путь во всех фрагментах кода в формате стиля Windows; вам нужно будет внести соответствующие изменения, если вы используете Linux или Mac.
Вы можете указать различные методы сжатия для сжатия файлов. Более новые методы BZIP2 и LZMA были добавлены в Python версии 3.3, а также есть некоторые другие инструменты, которые не поддерживают эти два метода сжатия. По этой причине безопасно просто использовать метод DEFLATED . Вы все равно должны попробовать эти методы, чтобы увидеть разницу в размере сжатого файла.
Сжатие нескольких файлов
Это немного сложно, так как вам нужно перебирать все файлы. Код ниже должен сжать все файлы с расширением pdf в данной папке:
На этот раз мы импортировали модуль os и использовали его метод walk() чтобы просмотреть все файлы и подпапки в нашей исходной папке. Я только сжимаю файлы PDF в каталоге. Вы также можете создавать разные архивные файлы для каждого формата, используя операторы if .
Если вы не хотите сохранять структуру каталогов, вы можете собрать все файлы вместе, используя следующую строку:
fantasy_zip.write(os.path.join(folder, file), file, compress_type = zipfile.ZIP_DEFLATED)Извлечение всех файлов
Вы можете использовать метод extractall() чтобы извлечь все файлы и папки из zip-файла в текущий рабочий каталог. Вы также можете передать имя папки в extractall() чтобы извлечь все файлы и папки в определенном каталоге. Если папка, которую вы передали, не существует, этот метод создаст ее для вас. Вот код, который вы можете использовать для извлечения файлов:
Если вы хотите извлечь несколько файлов, вам нужно будет указать имена файлов, которые вы хотите извлечь в виде списка.
Извлечение отдельных файлов
Это похоже на извлечение нескольких файлов. Одно из отличий состоит в том, что на этот раз вам нужно сначала указать имя файла и путь для его извлечения позже. Также вам нужно использовать метод extract() вместо extractall() . Вот базовый фрагмент кода для извлечения отдельных файлов.
Чтение Zip-файлов
Использование метода namelist() объекта ZipFile вернет список всех членов архива по имени. Чтобы получить информацию о конкретном файле в архиве, вы можете использовать метод getinfo() объекта ZipFile. Это даст вам доступ к информации, относящейся к этому файлу, такой как сжатый и несжатый размер файла или время его последнего изменения. Мы вернемся к этому позже.
Вызов getinfo() по одному для всех файлов может быть утомительным процессом, когда нужно обработать много файлов. В этом случае вы можете использовать метод infolist() чтобы вернуть список, содержащий объект ZipInfo для каждого отдельного члена в архиве. Порядок этих объектов в списке такой же, как и у настоящих zip-файлов.
Чтобы получить сжатый размер отдельного файла из архива, вы можете использовать атрибут compress_size . Точно так же, чтобы узнать несжатый размер, вы можете использовать атрибут file_size .
В следующем коде используются свойства и методы, которые мы только что обсудили, для извлечения только тех файлов, которые имеют размер менее 1 МБ.
Упаковываем и распаковываем файлы, а также управляем файловыми архивами в любых нужных нам форматах с помощью Python.
Упаковываем и распаковываем файлы, а также управляем файловыми архивами в любых нужных нам форматах с помощью Python.
Стандартная библиотека Python предоставляет модули и инструменты для решения практически любой прикладной задачи, и как вы понимаете, работа с файловыми архивами не является исключением. При этом будь то самые распространенные форматы архивации такие, как tar или zip , более специфические – gzip и bz2 , и совсем экзотические – lzma , в стандартной библиотеке Python есть все.
Имея в виду такое множество вариантов решения задачи, выбор определенного инструмента для ее решения становится не таким очевидным. Поэтому, чтобы помочь вам ориентироваться в специфике выбора инструментария для работы с файловыми архивами в зависимости от их форматов была написана эта статья. Ниже мы рассмотрим все основные модули и узнаем, как сжимать, распаковывать, проверять, тестировать и защищать наши архивы паролем с использованием стандартной библиотеки Python.
О форматах сжатия
Как упоминалось выше, Python в составе стандартной библиотеки содержит инструменты для работы с (почти) всеми существующими форматами архивации данных, которые только можно вообразить. Итак, для начала разберем основные из них, а затем рассмотрим, как вы можете их в дальнейшем использовать:
Упаковываем и распаковываем файлы
И так, у нас в наличии достаточно инструментов (модулей стандартной библиотеки) для работы с архивами в различных форматах. Использование большинства из них обычно не вызывает затруднений, есть также модули с множеством дополнительных специфических функций, но всех объединяет то, что они (как очевидно) включают самые основные (базовые) функции для упаковки (сжатия) и распаковки данных. Итак, давайте более предметно рассмотрим, как с их использованием выполняются эти базовые операции.
И прежде всего это будет модуль zlib . Он разработан на базе одноименной низкоуровневой библиотеки и обеспечивает удобный интерфейс для ее использования, поэтому сама она не так широко используется. Рассмотрим базовые операции упаковку/распаковку файлов:
В примере кода выше в качестве “подопытного” мы используем файл с именем data . В общем случае конечно же можно взять любой файл, но, например, в ОС Linux можно сгенерировать его с помощью команды head -c 1MB </dev/zero > data . В результате получаем файл с размером 1 МБ и бинарным содержимым в виде нулей. Далее мы открываем и считываем его в память, а затем используем функцию compress для создания сжатых данных, которые затем записываются в выходной файл compressed_data . Чтобы продемонстрировать то, что мы можем восстановить данные обратно, мы снова открываем сжатый файл и используем для его обработки функцию decompress . Операторы print выводят в терминале информацию, что размеры как сжатых, так и распакованных файлов данных совпадают.
Следующий формат архивации и модуль, который вы можете применить на практике – это bz2 . Его можно использовать очень похожим образом как и zlib в примере выше:
Неудивительно, что интерфейс этих модулей в значительной степени идентичен. Поэтому, чтобы показать что-то поинтереснее, в приведенном выше примере мы упростили (сократили) код сжатия прочитанного содержимого и создания нового файла практически до одной строки, а также использовали функцию os.stat для проверки размера файлов.
Последний из рассмотренных в этой статье модулей является низкоуровневый lzma . И пять же, чтобы продемонстрировать другие практики написания кода, давайте, на этот раз, сделаем инкрементное (последовательное) сжатие файла блоками заданного размера:
Как и в примерах выше, мы начинаем с создания исходного файла, состоящего из набора слов, извлеченных из словаря в /usr/share/dict/words . Это сделано для того, чтобы мы смогли впоследствии проверить, что распакованные данные идентичны оригиналу.
Чтобы убедиться, что все работает так, как нам надо, открываем и распаковываем файл обычным способом, а затем выводим в окно терминала пару слов из файла.
Переходим к модулям более высокого уровня – давайте теперь используем модуль gzip для тех же задач:
В этом примере мы объединили возможности модулей gzip и shutils . И может показаться, что ранее мы делали те же базовые операции сжатие/распаковка, как в примерах выше с модулями zlib и bz2 . Но благодаря функции shutil.copyfileobj мы можем производить поблочное инкрементное сжатие файла без необходимости осуществлять непосредственно перебор блоков данных в цикле, как мы это делали в примере использования модуля lzma .
Одним из преимуществ модуля gzip является то, что он предоставляет интерфейс для управления работой модуля из командной строки. И это работает не только в Linux, модули gzip и gunzip интегрированы непосредственно в установочные пакеты Python, и могут вызываться из командной сроки следующим образом:
Берем Большой молоток
Если вам удобнее использовать форматы архивов zip или tar , то в этот раздел вам будет интересен. В нем мы подробнее рассмотрим работу с соответствующими модулями. Помимо основных операций сжатия/распаковки, модули zip или tar предоставляют другие весьма полезные методы, например, такие как проверка контрольных сумм, использование паролей или получение списка файлов в архиве (без его распаковки). Итак, давайте посмотрим их в действии.
Это довольно большой фрагмент кода, но он наглядно демонстрирует наиболее важные возможности модуля zipfile . В примере мы создаем ZIP-архив с помощью диспетчера контекста ZipFile , использующегося в режиме записи "w" (write), а затем в созданный архив добавляем файлы. Как вы можете заметить, нам не нужно предварительно открывать файлы, которые добавляем, и считывать куда-либо их содержимое. Все, что нам нужно сделать, это вызвать метод write и передать в него имя добавляемого файла (путь к нему). После добавления файлов в архив устанавливаем для него пароль с помощью метода setpassword .
Далее, чтобы продемонстрировать, что все сработало так как надо, открываем архив. Перед чтением файлов из него с помощью метода testzip проверяем соответствие их контрольной суммы CRC и значения, указанного в заголовке. Затем используя метод infolist получаем информацию о файлах, находящихся в архиве. В этом примере мы просто выводим в терминале список объектов типа ZipInfo , но вы также можете получить значение их атрибутов: получить CRC, размер, параметры сжатия и т.д.
После проверки файлов в архиве открываем и прочитаем один из них, а затем выведем его содержимое в терминале. Мы видим, что его содержимое соответствует ожидаемому, поэтому можем продолжить и извлечь его в новый файл по заданному пути /tmp/ .
Помимо создания архивов и чтения файлов из них, модуль zipfile позволяет добавлять файлы к существующим архивам. Для этого все, что нам нужно сделать – это изменить режим доступа к архиву на "a" (append):
Как и в случае с модулем gzip , модули zipfile и tarfile также предоставляют интерфейс командной строки. Чтобы выполнить в терминале простейшие операции архивирования и распаковки, можно воспользоваться следующими приемами:
И последнее, но не менее важное. Рассмотрим подробнее модуль tarfile . Синтаксис его использования схож с zipfile , но он предоставляет некоторые дополнительные функции:
Мы начинаем с базовой операции создания архива, но, как можем заметить, здесь мы используем режим доступа "w:gz" , который указывает, что мы хотим использовать определенный тип сжатия GZ. После этого мы добавляем все необходимые файлы в архив. С помощью модуля tarfile мы также можем добавлять в архив символические ссылки или целые директории с содержимым, которое будет добавлено в архив рекурсивно.
Затем, чтобы убедиться, что все файлы действительно присутствуют в архиве, мы используем метод getmembers . Чтобы получить информацию об отдельных файлах, находящихся в архиве, используется метод gettarinfo , также он предоставляет содержимое всех атрибутов файлов.
Модуль tarfile содержит еще одну интересную функцию, которую мы не увидим у других, ранее рассмотренных модулей, а именно возможность изменять атрибуты файлов при их добавлении в архив. В приведенном выше фрагменте кода мы изменяем режим доступа к файлу, передав в качестве параметра функцию filter , которая изменяет значение соответствующего атрибута файла TarInfo.mode . Это значение должно быть представлено в виде восьмеричного числа, в нашем примере это 0o100600 . Вызов функции для добавляемого в архив файла устанавливает его права доступа 0600 или -rw------- .
Чтобы получить полный список файлов после добавления их в архив, вызываем метод list , который выводит в терминале результат, аналогичный команде ls -l .
Последнее, что мы еще можем сделать с tar архивом – это открыть его и извлечь содержимое. Для этого открываем его в режиме "r:gz" , явно указывая тип сжатия. Получаем объект member , который содержит информацию о всех файлах, упакованных в архиве. Используя строковое значение, соответствующее имени файла "words3.txt" , проверяем, действительно ли он находится в архиве, и извлекаем его в указанное место:
Заключение
Как видите, модули Python предоставляют множество функций для работы с архивами, как низкого, так и высокого уровня, как общие (базовые), так и весьма специфические. Что вы выберете, зависит от конкретной задачи и требований к результату ее решения. В основном я бы рекомендовал использовать модули общего назначения zipfile или tarfile , и прибегать к lzma и ему подобным только в том случае, если вам это действительно нужно.
Я попытался охватить все наиболее распространенные варианты использования этих модулей, чтобы дать вам обзор их возможностей, но, очевидно, в каждом из этих модулей есть гораздо больше полезных функций, объектов, атрибутов и т. д., Поэтому ознакомьтесь с их документацией.
Читайте также: