Работа с ZIP-архивами в Python: короткая инструкция
За 15 минут научитесь создавать, читать и распаковывать ZIP-архивы средствами стандартной библиотеки Python — без сторонних пакетов и без утилиты zip в системе.

К концу этой инструкции вы будете уметь три вещи: собрать несколько файлов в один .zip, посмотреть, что лежит внутри архива, не распаковывая его, и вытащить содержимое на диск. Всё делается модулем zipfile, который входит в стандартную библиотеку — ничего доустанавливать через pip не нужно. Примеры проверены на Python 3.12, но работают начиная с 3.6, а параметр compresslevel — с 3.7.
Что нужно до начала
- Python 3.6 или новее. Проверьте командой
python --versionв терминале — должно вывести что-то вродеPython 3.12.4. - Права на запись в папку, где вы будете создавать и распаковывать архивы. Если работаете на сервере — убедитесь, что каталог принадлежит вашему пользователю.
- Пара тестовых файлов, чтобы было что архивировать. Дальше в примерах это
report.txtиdata.csv.
Модуль zipfile уже установлен вместе с Python — отдельная строка import zipfile в начале скрипта, и всё готово.
Шаг 1. Создать архив из нескольких файлов
Открываем архив в режиме 'w' (запись) и добавляем в него файлы методом write(). Первый аргумент — путь к файлу на диске, второй (необязательный) arcname — под каким именем файл будет лежать внутри архива.
import zipfile
# Создаём архив и кладём в него два файла
with zipfile.ZipFile('archive.zip', 'w', zipfile.ZIP_DEFLATED) as zf:
zf.write('report.txt') # попадёт как report.txt
zf.write('data.csv', arcname='exports/data.csv') # попадёт в подпапку exports
ZIP_DEFLATED включает сжатие. Без него (по умолчанию ZIP_STORED) файлы кладутся как есть — быстрее, но крупнее.
Как понять, что получилось: рядом со скриптом появился файл archive.zip. Откройте его любым архиватором — внутри должны быть report.txt и папка exports с data.csv.
Если файла на диске нет, но данные есть в памяти
Когда содержимое сгенерировано в коде и на диск его писать не хочется, используйте writestr() — он принимает имя внутри архива и строку или байты.
import zipfile
text = 'id,name\n1,Иван\n2,Мария\n'
with zipfile.ZipFile('archive.zip', 'w', zipfile.ZIP_DEFLATED) as zf:
zf.writestr('users.csv', text)
Шаг 2. Посмотреть, что внутри, не распаковывая
Открываем архив в режиме 'r' (чтение) и вызываем namelist() — он вернёт список имён всех записей. Метод infolist() даёт больше: размер до и после сжатия, дату.
import zipfile
with zipfile.ZipFile('archive.zip', 'r') as zf:
for name in zf.namelist():
print(name)
# Подробности по каждому файлу
for info in zf.infolist():
print(f'{info.filename}: {info.file_size} байт '
f'(сжато до {info.compress_size})')
Как понять, что получилось: в терминале появится список имён файлов, а во втором цикле — их размеры. Если архив создан с ZIP_DEFLATED, у текстовых файлов compress_size будет заметно меньше file_size.
Шаг 3. Распаковать архив
Метод extractall() распаковывает всё содержимое в указанную папку. Если папки нет, Python создаст её сам.
import zipfile
with zipfile.ZipFile('archive.zip', 'r') as zf:
zf.extractall('unpacked') # всё содержимое ляжет в папку unpacked
Нужен только один файл — используйте extract() с его именем:
import zipfile
with zipfile.ZipFile('archive.zip', 'r') as zf:
zf.extract('report.txt', 'unpacked')
А если файл нужен не на диске, а в памяти — прочитайте его содержимое методом read(), он вернёт байты:
import zipfile
with zipfile.ZipFile('archive.zip', 'r') as zf:
raw = zf.read('users.csv') # bytes
text = raw.decode('utf-8') # если внутри текст
print(text)
Как понять, что получилось: после extractall в папке unpacked лежат все файлы из архива с сохранённой структурой подпапок.
Не вызывайтеextractall()для архивов из ненадёжного источника без проверки. Имена вроде../../etc/passwdвнутри архива могут увести распаковку за пределы целевой папки — это классическая атака Zip Slip. В Python 3.6.2 и новееextractallуже нормализует пути и не даёт выйти наружу, но данные из интернета всё равно стоит проверять.
Добавить файлы в существующий архив
Режим 'a' (append) дописывает записи в готовый архив, не затирая старые. Открытие в 'w' вместо этого создаст архив заново и всё прежнее удалит — частая причина «пропавших» файлов.
import zipfile
with zipfile.ZipFile('archive.zip', 'a', zipfile.ZIP_DEFLATED) as zf:
zf.write('notes.txt')
Уровень сжатия
С Python 3.7 у ZipFile есть параметр compresslevel. Для ZIP_DEFLATED он принимает значения от 0 до 9: 9 сжимает сильнее, но дольше.
| Настройка | Значение | Когда использовать |
|---|---|---|
| compression | ZIP_STORED | Без сжатия — уже сжатые файлы (jpg, mp4, pdf) |
| compression | ZIP_DEFLATED | Универсальный выбор для текста и данных |
| compresslevel | 1 | Быстро, минимальное сжатие |
| compresslevel | 6 | Значение по умолчанию, баланс |
| compresslevel | 9 | Максимум сжатия, медленнее всего |
import zipfile
with zipfile.ZipFile('archive.zip', 'w',
compression=zipfile.ZIP_DEFLATED,
compresslevel=9) as zf:
zf.write('report.txt')
Если не получилось
FileNotFoundError: [Errno 2] No such file or directory: 'report.txt'— файл, который вы передали вwrite(), не найден по указанному пути. Проверьте, из какой папки запускается скрипт: относительный путь считается от текущего рабочего каталога, а не от расположения.py-файла.zipfile.BadZipFile: File is not a zip file— файл повреждён или это вообще не ZIP. Откройте его сторонним архиватором, чтобы убедиться, что архив целый.PermissionError: [Errno 13] Permission denied— нет прав на запись в папку распаковки или на чтение архива. Проверьте владельца и права каталога.- Кириллица в именах превратилась в кракозябры. Старые архивы, созданные в Windows, могут хранить имена в кодировке cp866. Стандартный
zipfileне всегда угадывает кодировку — если имена важны, читайте их изinfolist()и перекодируйте вручную. - Архив создался, но пустой или в 22 байта. Скорее всего, блок
withзакрылся до вызоваwrite()или вы открыли существующий архив в режиме'w'и не добавили ничего нового.
Что дальше
Для больших наборов файлов посмотрите модуль shutil: функция shutil.make_archive() упаковывает целую папку одной строкой, а shutil.unpack_archive() распаковывает не только ZIP, но и tar. Если работаете с архивами в вебе — читайте и пишите их в память через io.BytesIO, чтобы не создавать временных файлов на диске. Полный список методов ZipFile и их параметров держите под рукой в официальной документации: она короткая и точная.
Проектная работа: От проблемы до защиты: продукт, этапы, вопросы комиссии
Спросить за 15 ₽Источники: zipfile — Work with ZIP archives. Python documentation, shutil — High-level file operations. Python documentation
Частые вопросы
У меня Python 3.6, параметр compresslevel не работает — что делать?
Как заархивировать целую папку со всеми вложенными файлами?
Можно ли поставить пароль на ZIP-архив стандартным модулем?
Архив открылся, но при распаковке кириллические имена стали нечитаемыми — почему?
Что будет с существующим архивом, если открыть его в режиме 'w'?
Насколько безопасно распаковывать архив из интернета?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.