Статьи

Сжатие и извлечение файлов в Python

Если вы какое-то время пользовались компьютерами, вы, вероятно, сталкивались с файлами с расширением .zip . Это специальные файлы, которые могут содержать сжатый контент многих других файлов, папок и подпапок. Это делает их довольно полезными для передачи файлов через Интернет. Знаете ли вы, что вы можете использовать Python для сжатия или извлечения файлов?

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

Это легко и требует очень мало кода. Мы начнем с импорта модуля zipfile, а затем откроем объект ZipFile в режиме записи, указав второй параметр как «w». Первый параметр — это путь к самому файлу. Вот код, который вам нужен:

1
2
3
4
5
6
import zipfile
         
jungle_zip = zipfile.ZipFile(‘C:\\Stories\\Fantasy\\jungle.zip’, ‘w’)
jungle_zip.write(‘C:\\Stories\\Fantasy\\jungle.pdf’, compress_type=zipfile.ZIP_DEFLATED)
 
jungle_zip.close()

Обратите внимание, что я буду указывать путь во всех фрагментах кода в формате стиля Windows; вам нужно будет внести соответствующие изменения, если вы используете Linux или Mac.

Вы можете указать различные методы сжатия для сжатия файлов. Более новые методы BZIP2 и LZMA были добавлены в Python версии 3.3, а также есть некоторые другие инструменты, которые не поддерживают эти два метода сжатия. По этой причине безопасно просто использовать метод DEFLATED . Вы все равно должны попробовать эти методы, чтобы увидеть разницу в размере сжатого файла.

Это немного сложно, так как вам нужно перебирать все файлы. Код ниже должен сжать все файлы с расширением pdf в данной папке:

01
02
03
04
05
06
07
08
09
10
11
12
import os
import zipfile
 
fantasy_zip = zipfile.ZipFile(‘C:\\Stories\\Fantasy\\archive.zip’, ‘w’)
 
for folder, subfolders, files in os.walk(‘C:\\Stories\\Fantasy’):
 
    for file in files:
        if file.endswith(‘.pdf’):
            fantasy_zip.write(os.path.join(folder, file), os.path.relpath(os.path.join(folder,file), ‘C:\\Stories\\Fantasy’), compress_type = zipfile.ZIP_DEFLATED)
 
fantasy_zip.close()

На этот раз мы импортировали модуль os и использовали его метод walk() чтобы просмотреть все файлы и подпапки в нашей исходной папке. Я только сжимаю файлы PDF в каталоге. Вы также можете создавать разные архивные файлы для каждого формата, используя операторы if .

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

1
fantasy_zip.write(os.path.join(folder, file), file, compress_type = zipfile.ZIP_DEFLATED)

Метод write() принимает три параметра. Первый параметр — это имя нашего файла, который мы хотим сжать. Второй параметр является необязательным и позволяет указать другое имя файла для сжатого файла. Если ничего не указано, используется оригинальное имя.

Вы можете использовать метод extractall() чтобы извлечь все файлы и папки из zip-файла в текущий рабочий каталог. Вы также можете передать имя папки в extractall() чтобы извлечь все файлы и папки в определенном каталоге. Если папка, которую вы передали, не существует, этот метод создаст ее для вас. Вот код, который вы можете использовать для извлечения файлов:

1
2
3
4
5
6
import zipfile
         
fantasy_zip = zipfile.ZipFile(‘C:\\Stories\\Fantasy\\archive.zip’)
fantasy_zip.extractall(‘C:\\Library\\Stories\\Fantasy’)
 
fantasy_zip.close()

Если вы хотите извлечь несколько файлов, вам нужно будет указать имена файлов, которые вы хотите извлечь в виде списка.

Это похоже на извлечение нескольких файлов. Одно из отличий состоит в том, что на этот раз вам нужно сначала указать имя файла и путь для его извлечения позже. Также вам нужно использовать метод extract() вместо extractall() . Вот базовый фрагмент кода для извлечения отдельных файлов.

1
2
3
4
5
6
import zipfile
         
fantasy_zip = zipfile.ZipFile(‘C:\\Stories\\Fantasy\\archive.zip’)
fantasy_zip.extract(‘Fantasy Jungle.pdf’, ‘C:\\Stories\\Fantasy’)
 
fantasy_zip.close()

Рассмотрим сценарий, в котором вам нужно проверить, содержит ли zip-архив определенный файл. До этого момента единственный вариант сделать это — извлечь все файлы из архива. Точно так же вам может потребоваться извлечь только те файлы, которые больше определенного размера. Модуль zipfile позволяет нам запрашивать содержимое архива, даже не распаковывая его.

Использование метода namelist() объекта ZipFile вернет список всех членов архива по имени. Чтобы получить информацию о конкретном файле в архиве, вы можете использовать метод getinfo() объекта ZipFile. Это даст вам доступ к информации, относящейся к этому файлу, такой как сжатый и несжатый размер файла или время его последнего изменения. Мы вернемся к этому позже.

Вызов getinfo() по одному для всех файлов может быть утомительным процессом, когда нужно обработать много файлов. В этом случае вы можете использовать метод infolist() чтобы вернуть список, содержащий объект ZipInfo для каждого отдельного члена в архиве. Порядок этих объектов в списке такой же, как и у настоящих zip-файлов.

Вы также можете напрямую прочитать содержимое определенного файла из архива, используя метод read(file) , где file — это имя файла, который вы намереваетесь прочитать. Для этого архив необходимо открыть в режиме чтения или добавления.

Чтобы получить сжатый размер отдельного файла из архива, вы можете использовать атрибут compress_size . Точно так же, чтобы узнать несжатый размер, вы можете использовать атрибут file_size .

В следующем коде используются свойства и методы, которые мы только что обсудили, для извлечения только тех файлов, которые имеют размер менее 1 МБ.

1
2
3
4
5
6
7
8
9
import zipfile
 
stories_zip = zipfile.ZipFile(‘C:\\Stories\\Funny\\archive.zip’)
 
for file in stories_zip.namelist():
    if stories_zip.getinfo(file).file_size < 1024*1024:
        stories_zip.extract(file, ‘C:\\Stories\\Short\\Funny’)
         
stories_zip.close()

Чтобы узнать время и дату последнего изменения определенного файла из архива, вы можете использовать атрибут date_time . Это вернет кортеж из шести значений. Значениями будут год, месяц, день месяца, часы, минуты и секунды в указанном порядке. Год всегда будет больше или равен 1980 году, а часы, минуты и секунды начинаются с нуля.

01
02
03
04
05
06
07
08
09
10
11
import zipfile
 
stories_zip = zipfile.ZipFile(‘C:\\Stories\\Funny\\archive.zip’)
 
thirsty_crow_info = stories_zip.getinfo(‘The Thirsty Crow.pdf’)
 
print(thirsty_crow_info.date_time)
print(thirsty_crow_info.compress_size)
print(thirsty_crow_info.file_size)
         
stories_zip.close()

Эта информация об исходном размере файла и размере сжатого файла может помочь вам решить, стоит ли сжимать файл. Я уверен, что это может быть использовано и в других ситуациях.

Как видно из этого руководства, использование модуля zipfile для сжатия файлов обеспечивает большую гибкость. Вы можете сжимать разные файлы в каталоге в разные архивы в зависимости от их типа, имени или размера. Вы также можете решить, хотите ли вы сохранить структуру каталогов или нет. Аналогично, при извлечении файлов вы можете извлекать их в нужное место, основываясь на ваших собственных критериях, таких как размер и т. Д.

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

Изучите Python с нашим полным руководством по питону, независимо от того, начинаете ли вы или начинающий программист, ищущий новые навыки.