Чтение, сжатие и распаковка ZIP-файлов в Python

Введение
Сжатие (zip) — удобный способ объединить несколько файлов в единый архив и уменьшить занимаемый объём данных. ZIP-архивы экономят место на диске и трафик при передаче по сети. Формат поддерживается во всех основных ОС: Windows, Linux и macOS.
ZIP использует безпотерьную компрессию (lossless), поэтому данные восстанавливаются без потерь после распаковки. При работе с архивами можно просматривать метаданные, извлекать содержимое по отдельности и выбирать методы сжатия.
Ниже показано, как читать, создавать и распаковывать ZIP с помощью модуля zipfile, а также когда стоит обратить внимание на альтернативы.
Важно: модуль zipfile стандартной библиотеки умеет читать зашифрованные архивы с простым паролем только частично; он не реализует современное AES‑шифрование. Для сильного шифрования используйте сторонние библиотеки.
Что такое модуль zipfile
Модуль zipfile — стандартный модуль Python для работы с ZIP-архивами. С его помощью можно:
- открывать и читать ZIP-файлы;
- просматривать списки файлов и их метаданные (время модификации, размеры);
- создавать архивы и добавлять файлы в них;
- извлекать содержимое в указанную директорию.
Поддерживаемые методы сжатия: ZIP_STORED (без сжатия), ZIP_DEFLATED (Deflate), ZIP_BZIP2, ZIP_LZMA. Модуль поддерживает расширение ZIP64, необходимое для файлов и архивов больше 4 ГиБ, но не поддерживает многотомные (multi-disk) архивы.
Краткое определение терминов:
- ZIP64: расширение формата ZIP для поддержки объёма и количества файлов больше ограничений классического ZIP (4 ГиБ, 65535 файлов).
- Deflate: наиболее распространённый алгоритм сжатия для ZIP.
Быстрая шпаргалка по API (cheat sheet)
- Открыть архив: ZipFile(‘archive.zip’, ‘r’)
- Создать/записать: ZipFile(‘archive.zip’, ‘w’) или ‘a’ для добавления
- Указать метод сжатия: ZipFile(…, compression=zipfile.ZIP_DEFLATED)
- Просмотреть содержимое: zip.namelist() или zip.infolist()
- Извлечь всё: zip.extractall(path)
- Извлечь один файл: zip.extract(member, path)
- Открыть файл внутри архива как файл-объект: zip.open(name)
Как запаковать файлы в ZIP (пример с пояснениями)
Ниже — функция, которая собирает все пути файлов в каталоге и возвращает список абсолютных путей. В примере используются pathlib и zipfile — это современно и читабельно.
# Пример: собрать все файлы в директории и запаковать их
from zipfile import ZipFile, ZIP_DEFLATED, ZIP_LZMA, ZIP_BZIP2
from pathlib import Path
import zipfile
def get_all_file_paths(directory: str):
"""Возвращает список путей ко всем файлам внутри directory (рекурсивно)."""
base = Path(directory)
file_paths = [str(p) for p in base.rglob('*') if p.is_file()]
return file_paths
# Путь к папке, которую хотим заархивировать
directory = './pythonzip'
file_paths = get_all_file_paths(directory)
print('Список файлов для архивации:')
for p in file_paths:
print(p)
# Создаём ZIP с дефолтным сжатием Deflate
with ZipFile('my_archive.zip', 'w', compression=ZIP_DEFLATED, allowZip64=True) as zf:
base = Path(directory)
for file_path in file_paths:
# Добавляем файл в архив с относительным именем (удобно при извлечении)
arcname = str(Path(file_path).relative_to(base))
zf.write(file_path, arcname=arcname)
print('Все файлы заархивированы в my_archive.zip')Пояснения и рекомендации:
- arcname позволяет контролировать, как файл будет называться внутри архива (обычно используют относительный путь, чтобы не хранить абсолютные пути).
- allowZip64=True включён по умолчанию в современных версиях Python и нужен для больших архивов (>4 ГиБ).
- Для совместимости с более старыми утилитами можно использовать ZIP_STORED (без сжатия) или ZIP_DEFLATED.
Альтернативный быстрый способ — shutil.make_archive:
import shutil
shutil.make_archive('my_archive', 'zip', root_dir='pythonzip')shutil.make_archive удобен для простых задач, но даёт меньше гибкости (нельзя тонко настроить имена внутри архива и метаданные).
Как распаковать ZIP-файл
Пример извлечения всего архива в текущую директорию или в указанную папку:
from zipfile import ZipFile
file_name = 'extract.zip'
with ZipFile(file_name, 'r') as zf:
# Содержимое архива
zf.printdir()
print('Идёт распаковка...')
zf.extractall(path='output_folder') # по умолчанию — текущая директория
print('Распаковка завершена.')Если нужно извлечь один файл или проверить его содержимое без распаковки на диск, используйте zipfile.ZipFile.open():
with ZipFile('my_archive.zip', 'r') as zf:
with zf.open('docs/readme.txt') as f:
text = f.read().decode('utf-8')
print(text)Сжатие, методы и производительность
Доступные методы сжатия:
- ZIP_STORED — без сжатия. Полезно для уже сжатых данных (видео, изображения, архивы внутри архива).
- ZIP_DEFLATED — дефолтный и обычно наиболее универсальный выбор (использует zlib).
- ZIP_BZIP2 — иногда даёт лучшее сжатие на массированных текстовых данных, но медленнее.
- ZIP_LZMA — высокое сжатие, но более высокая нагрузка на CPU.
Правильный выбор зависит от типа данных и требований к скорости/размеру архива.
Ограничения и случаи, когда ZIP не подойдёт
- Большие наборы данных: для «потоковой» упаковки больших данных лучше использовать tar + gzip/xz или специализированные инструменты.
- Сохранение метаданных POSIX (права, владельцы): zip по умолчанию не сохраняет все POSIX-атрибуты; tar лучше подходит для резервных копий на Unix.
- Многотомные архивы (split archives): zipfile не поддерживает multi-disk.
- Сильное шифрование: стандартный zip использует устаревшую схему; для AES‑шифрования нужна библиотека pyzipper или внешние утилиты.
- Кодировка имён файлов: в старых ZIP-архивах могут быть проблемы с кодировкой имён (особенно при смешанной Windows/Unix среде).
Альтернативные инструменты и подходы
- tarfile (стандартная библиотека) — упаковка без сжатия; часто комбинируется с gzip/xz: tar.gz, tar.xz.
- shutil.make_archive — простая обёртка для быстрого создания ZIP/ TAR архивов.
- pyzipper — библиотека с поддержкой AES шифрования и более современных возможностей.
- pyminizip — удобна для создания AES-зашифрованных ZIP из Python.
- 7‑Zip / p7zip — мощный инструмент для сжатия через subprocess; поддерживает LZMA2, сильное шифрование и мультиформатность.
- libarchive — через binding’и для Python, поддерживает множество форматов.
Совет: если вам нужно обеспечить безопасность данных при хранении/передаче — используйте проверенные AES‑решения и управляйте ключами отдельно.
Советы по безопасности и соответствию (GDPR/личные данные)
- Не храните личные данные в незашифрованных архивах при переносе вне доверенной сети.
- Для соответствия требованиям шифруйте архивы с использованием современных алгоритмов (AES) и храните ключи отдельно.
- Логи и метаданные (время модификации, имена файлов) могут раскрывать чувствительную информацию — учитывайте это при совместном использовании архива.
- При автоматизированной архивации убедитесь, что права доступа к созданным ZIP-файлам ограничены (правильные права в файловой системе).
Практический чек-лист по ролям
Разработчик
- Проверить arcname и относительные пути
- Установить allowZip64=True для больших данных
- Обработать исключения (BadZipFile, LargeZipFile)
Системный администратор / DevOps
- Автоматизировать создание архивов (cron/CI)
- Контролировать права и шифрование при переносе
- Ставить SLI/SLO на время бэкапа и восстановления (время архивации/восстановления)
Аналитик данных
- Фильтровать ненужные файлы (tmp, .cache) перед архивированием
- Документировать структуру архива (README внутри ZIP)
Таблица сравнения: ZIP vs TAR vs 7z vs RAR (обзор)
- ZIP: универсален, широко поддерживается, дефолтно без AES в zipfile; хорош для кроссплатформенной доставки.
- TAR (+ gzip/xz): лучше для резервного копирования на Unix (сохраняет права, владельцев); tar.gz — быстрый компромисс.
- 7z: очень хорошее сжатие, современное шифрование, менее распространён по умолчанию в ОС.
- RAR: хорошее сжатие и поддержка AES‑шифрования, но проприетарный формат (потребуется внешний инструмент).
Отладка проблем с ZIP
- Ошибка BadZipFile: файл повреждён или неполный — проверьте контрольную сумму и целостность передачи.
- Проблемы с кодировкой имён: при создании архивов на одной ОС и извлечении на другой проверьте, используется ли UTF-8 для имён файлов.
- Большие файлы: убедитесь, что включён ZIP64 и что используемые утилиты поддерживают его.
Мини‑методология для автоматической архивации (SOP)
- Составить список включаемых/исключаемых файлов (.gitignore‑подобный фильтр).
- Собрать относительные пути и добавить контрольный README с версией/датой.
- Запаковать в ZIP с выбранным методом сжатия и allowZip64=True.
- Проверить целостность архива (например, попытаться распаковать в temp-репозиторий).
- Заархивировать и, при необходимости, зашифровать архив отдельно (AES) перед передачей.
- Удалить временные файлы и зафиксировать метаданные в журнале.
Краткий словарь (1‑строчка)
- zipfile: модуль Python для работы с ZIP-архивами; ZipFile — класс для чтения/записи.
- ZIP64: расширение для поддержки больших файлов/архивов (>4 ГиБ).
- Deflate: алгоритм сжатия, используемый в большинстве ZIP‑архивов.
Заключение
Модуль zipfile — надёжный инструмент для большинства задач архивации в Python: создание архивов, просмотр содержимого и извлечение. Для простых задач вполне хватает zipfile и shutil.make_archive. Для сценариев, где важна совместимость с Unix‑метаданными, многотомные архивы или сильное шифрование, рассмотрите tar, 7z, RAR или специализированные Python‑библиотеки (pyzipper, pyminizip).
Короткое резюме — выбирайте инструмент исходя из требований к совместимости, размерам, сохранению метаданных и безопасности: ZIP удобен и кроссплатформен, tar — для Unix‑бэкапов, 7z/pyzipper — для сильного сжатия и шифрования.
Критерии приёмки
- Архив создаётся без ошибок и извлекается штатными средствами ОС.
- Имена внутри архива — относительные и предсказуемые (arcname).
- Для больших архивов не возникают ошибки, связанные с ограничениями 4 ГиБ (ZIP64 включён).
- Чувствительные данные зашифрованы и ключи хранятся безопасно.
Сводка основных выводов:
- zipfile покрывает обычные задачи архивации в Python.
- Для AES‑шифрования и сложных сценариев используйте сторонние библиотеки.
- Всегда проверяйте совместимость формата и кодировку имён при кроссплатформенной работе.
Похожие материалы
Очистка истории в Microsoft Edge
Как сделать скриншот в играх на ПК
Google Assistant на Raspberry Pi — голос и GPIO
Netflix: «Дополнительный участник» — цена и как добавить
Как скрывать окна автозапуска в macOS Ventura