3 способа создания ZIP-архива директории в Python с примерами кода
Для кого эта статья:
- Python-разработчики, желающие улучшить свои навыки работы с архивами
- Специалисты, занимающиеся автоматизацией процессов и бэкапа данных
Студенты и новички в программировании, стремящиеся освоить продвинутые техники работы с файлами в Python
Работа с архивами в Python — одна из тех обыденных задач, которые могут оказаться неожиданно сложными без должных знаний. Когда проект разрастается до тысяч файлов или вам нужно автоматизировать бэкапы, вопрос эффективного создания ZIP-архивов становится критически важным. Я протестировал все основные методы архивирования директорий в Python и готов поделиться тремя проверенными способами, которые сэкономят ваше время и ресурсы. От базовых встроенных модулей до продвинутых решений с паролями — это исчерпывающее руководство покроет все ваши потребности в zip-архивировании. 🗂️
Хотите освоить Python на профессиональном уровне? Курс Python-разработки от Skypro научит вас не только базовым принципам программирования, но и продвинутым техникам работы с файловой системой, включая создание и управление архивами. Наши выпускники уже через 8 месяцев создают автоматизированные системы резервного копирования для крупных компаний. Начните своё путешествие в мир Python уже сегодня!
Модуль zipfile: базовый способ создания zip-архива в Python
Модуль zipfile — это встроенный в Python инструмент для работы с ZIP-архивами, который доступен "из коробки" без необходимости устанавливать дополнительные библиотеки. Это первый и самый фундаментальный способ создания архивов, который должен знать каждый Python-разработчик.
Давайте рассмотрим базовый пример создания ZIP-архива директории:
import os
import zipfile
def zip_directory(directory_path, zip_path):
# Создаем объект ZipFile
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
# Проходимся по всем файлам и поддиректориям
for root, _, files in os.walk(directory_path):
for file in files:
file_path = os.path.join(root, file)
# Определяем путь внутри архива относительно исходной директории
arcname = os.path.relpath(file_path, os.path.dirname(directory_path))
# Добавляем файл в архив
zipf.write(file_path, arcname)
# Использование
zip_directory('/path/to/folder', '/path/to/archive.zip')
Этот код проходит по всем файлам в указанной директории с помощью os.walk(), добавляя каждый файл в архив с сохранением относительной структуры папок. Метод zipfile.ZIP_DEFLATED указывает на использование алгоритма сжатия DEFLATE, который обеспечивает хороший компромисс между скоростью и степенью сжатия. 📦
Алексей, ведущий разработчик Python
Однажды мне поручили создать систему автоматического архивирования логов для проекта, генерирующего более 2 ГБ данных ежедневно. Первая моя реализация использовала простой скрипт с модулем zipfile. Это решение работало нормально в течение первой недели, но вскоре стало очевидно, что при больших объемах данных скрипт начинал заметно тормозить, а в некоторых случаях — потреблять слишком много оперативной памяти.
Проблема заключалась в том, что я загружал все файлы в память перед архивированием. Решение оказалось простым: модификация скрипта для потокового чтения файлов и немедленного добавления их в архив. Я заменил блок кода на тот, что приведен выше, где каждый файл обрабатывается последовательно. Производительность выросла на 40%, а потребление RAM снизилось почти в 2 раза.
Преимущества использования zipfile включают:
- Полный контроль над процессом архивирования
- Возможность добавления отдельных файлов без необходимости архивировать всю директорию
- Доступ к низкоуровневым параметрам сжатия
- Нет зависимостей от сторонних библиотек
Однако у этого подхода есть и ограничения:
- Требуется написание дополнительного кода для обхода директорий
- Необходимо вручную обрабатывать относительные пути файлов
- Может быть избыточным для простых задач архивирования
| Параметр | Описание | Значения |
|---|---|---|
file | Путь к создаваемому архиву или файловый объект | Строка или файловый объект |
mode | Режим открытия архива | 'r', 'w', 'a', 'x' |
compression | Алгоритм сжатия | ZIPSTORED, ZIPDEFLATED, ZIPBZIP2, ZIPLZMA |
allowZip64 | Поддержка архивов >4 ГБ | True/False (по умолчанию True) |

Метод shutil.make_archive: простое архивирование директорий
Модуль shutil предоставляет высокоуровневые функции для операций с файлами и директориями, включая функцию make_archive, которая значительно упрощает процесс архивирования всей директории. Если вам не требуется тонкая настройка процесса архивирования, этот метод будет оптимальным выбором. 🧰
Вот как выглядит создание ZIP-архива директории с помощью shutil:
import shutil
# Создание архива директории
archive_path = shutil.make_archive(
base_name='archive_name', # Имя архива (без расширения)
format='zip', # Формат архива
root_dir='path/to/parent', # Родительская директория (опционально)
base_dir='directory_name' # Директория для архивирования
)
print(f"Архив создан: {archive_path}")
Функция make_archive автоматически обрабатывает обход директорий и добавление файлов в архив, что делает код намного компактнее и читабельнее по сравнению с использованием zipfile.
Основные преимущества использования shutil.make_archive:
- Минимальное количество кода для архивирования всей директории
- Автоматическое сохранение структуры директорий
- Поддержка различных форматов архивов (zip, tar, gztar и др.)
- Простой и понятный интерфейс
Рассмотрим более детальный пример с дополнительными опциями:
import shutil
import os
from datetime import datetime
# Получаем текущую дату для имени архива
current_date = datetime.now().strftime('%Y-%m-%d')
# Директория для архивирования
directory_to_zip = '/path/to/project'
# Создаем архив с датой в имени
output_filename = f'backup_{current_date}'
output_path = os.path.join('/path/to/backups', output_filename)
# Создаем архив
archive_path = shutil.make_archive(
base_name=output_path,
format='zip',
root_dir=os.path.dirname(directory_to_zip),
base_dir=os.path.basename(directory_to_zip)
)
print(f"Создан бэкап проекта: {archive_path}")
Здесь мы используем shutil.make_archive для создания датированного архива проекта, что может быть полезно для систем резервного копирования.
Параметры root_dir и base_dir дают гибкость в определении того, какие части пути будут включены в архив. Если вы укажете только base_dir, то архив будет содержать файлы относительно текущего рабочего каталога.
| Функция | Сложность использования | Уровень контроля | Объем кода |
|---|---|---|---|
| zipfile.ZipFile | Высокая | Максимальный | 15-20 строк |
| shutil.make_archive | Низкая | Средний | 3-5 строк |
| PyZipFile | Средняя | Высокий | 10-15 строк |
Библиотека PyZipFile: расширенные возможности zip-сжатия
PyZipFile — это подкласс ZipFile из стандартной библиотеки zipfile, специализированный на архивировании Python-модулей. Этот инструмент особенно полезен для разработчиков Python-пакетов или тех, кто работает с проектами, содержащими много Python-кода. 🐍
Основное отличие PyZipFile от обычного ZipFile заключается в его способности автоматически компилировать Python-файлы в байт-код (.pyc) перед добавлением их в архив, что может ускорить загрузку модулей при их последующем использовании.
Вот как можно создать архив Python-модулей с помощью PyZipFile:
import os
import zipfile
from zipfile import PyZipFile, ZIP_DEFLATED
def create_python_archive(directory_path, zip_path, compression=ZIP_DEFLATED, optimize=-1):
"""
Создает архив Python-модулей с оптимизацией.
Args:
directory_path: Путь к директории с Python-модулями
zip_path: Путь для сохранения ZIP-архива
compression: Метод сжатия (по умолчанию ZIP_DEFLATED)
optimize: Уровень оптимизации байт-кода (-1, 0, 1 или 2)
"""
with PyZipFile(zip_path, mode='w', compression=compression) as zipf:
# Рекурсивно добавляем все Python-пакеты
zipf.writepy(directory_path, optimize=optimize)
# Добавляем не-Python файлы (документация, данные и т.д.)
for root, dirs, files in os.walk(directory_path):
for file in files:
if not file.endswith(('.py', '.pyc', '.pyo')):
full_path = os.path.join(root, file)
rel_path = os.path.relpath(full_path, os.path.dirname(directory_path))
zipf.write(full_path, rel_path)
# Использование
create_python_archive('/path/to/python_project', '/path/to/python_modules.zip', optimize=2)
Параметр optimize контролирует уровень оптимизации байт-кода:
- -1: Использовать значение по умолчанию для интерпретатора Python
- 0: Без оптимизации (эквивалент python -m)
- 1: Удаляет assert-выражения (эквивалент python -O)
- 2: Удаляет assert-выражения и docstrings (эквивалент python -OO)
Преимущества использования PyZipFile:
- Автоматическая компиляция Python-файлов в байт-код
- Оптимизация байт-кода для ускорения загрузки
- Упрощенное распространение Python-пакетов
- Защита исходного кода от случайного изменения
Однако стоит помнить, что PyZipFile не обеспечивает настоящую обфускацию кода или защиту интеллектуальной собственности, так как байт-код Python относительно легко декомпилировать.
Для проектов, которые не являются Python-пакетами, использование PyZipFile может быть избыточным, и стандартные методы архивирования будут более подходящими.
Защита zip-архивов паролем и установка уровня сжатия
Защита конфиденциальных данных и оптимизация размера архивов — важные аспекты при работе с ZIP-файлами в Python. Рассмотрим, как установить пароль на архив и настроить уровень сжатия для достижения оптимального баланса между размером файла и скоростью архивирования. 🔐
Игорь, DevOps-инженер
В нашем проекте возникла необходимость ежедневно архивировать и передавать финансовые отчёты между различными системами. Данные содержали конфиденциальную информацию, поэтому простого архивирования было недостаточно.
Я реализовал систему на Python с использованием библиотеки pyzipper для создания защищённых паролем архивов. Ключевым моментом было использование AES-шифрования, так как стандартная ZIP-защита (ZipCrypto) имеет известные уязвимости.
Наш скрипт генерировал уникальные пароли для каждой передачи, используя секретный ключ и метку времени. Эти пароли передавались по отдельному защищённому каналу. После внедрения этой системы мы не только обеспечили безопасность данных, но и сократили размер передаваемых файлов примерно на 70%, что значительно ускорило процесс обмена информацией.
К сожалению, стандартный модуль zipfile в Python не поддерживает установку паролей на архивы. Для создания защищённых паролем ZIP-архивов необходимо использовать сторонние библиотеки, такие как pyzipper.
Вот пример создания защищённого паролем архива с использованием pyzipper:
# Установите библиотеку: pip install pyzipper
import os
import pyzipper
def create_encrypted_zip(directory_path, zip_path, password):
"""
Создаёт защищённый паролем ZIP-архив с поддержкой AES-шифрования.
Args:
directory_path: Путь к директории для архивирования
zip_path: Путь для сохранения ZIP-архива
password: Пароль для защиты архива
"""
# Преобразуем пароль в байты, если он в виде строки
if isinstance(password, str):
password = password.encode('utf-8')
# Создаём защищённый архив с AES-шифрованием
with pyzipper.AESZipFile(zip_path,
'w',
compression=pyzipper.ZIP_LZMA, # Используем LZMA для лучшего сжатия
encryption=pyzipper.WZ_AES) as zipf:
zipf.setpassword(password)
# Проходимся по всем файлам и поддиректориям
for root, _, files in os.walk(directory_path):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, os.path.dirname(directory_path))
# Добавляем файл в архив
zipf.write(file_path, arcname)
# Использование
create_encrypted_zip('/path/to/sensitive_data', '/path/to/encrypted_archive.zip', 'strong-password-123')
Что касается уровней сжатия, стандартный модуль zipfile поддерживает несколько алгоритмов сжатия:
ZIP_STORED(0) — без сжатия, просто хранение файловZIP_DEFLATED(8) — стандартный алгоритм сжатия (хороший баланс между скоростью и размером)ZIP_BZIP2(12) — более сильное сжатие, но медленнееZIP_LZMA(14) — наиболее сильное сжатие, но самое медленное
Выбор метода сжатия зависит от ваших приоритетов: скорость создания архива или минимальный размер.
Пример настройки уровня сжатия в стандартном zipfile:
import zipfile
import os
def zip_with_compression_level(directory_path, zip_path, compression_method=zipfile.ZIP_DEFLATED):
"""
Создаёт ZIP-архив с указанным методом сжатия.
Args:
directory_path: Путь к директории для архивирования
zip_path: Путь для сохранения ZIP-архива
compression_method: Метод сжатия (ZIP_STORED, ZIP_DEFLATED, ZIP_BZIP2, ZIP_LZMA)
"""
with zipfile.ZipFile(zip_path, 'w', compression=compression_method) as zipf:
for root, _, files in os.walk(directory_path):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, os.path.dirname(directory_path))
zipf.write(file_path, arcname)
# Примеры использования с разными методами сжатия
zip_with_compression_level('/path/to/data', '/path/to/no_compression.zip', zipfile.ZIP_STORED)
zip_with_compression_level('/path/to/data', '/path/to/standard_compression.zip', zipfile.ZIP_DEFLATED)
zip_with_compression_level('/path/to/data', '/path/to/bzip2_compression.zip', zipfile.ZIP_BZIP2)
zip_with_compression_level('/path/to/data', '/path/to/lzma_compression.zip', zipfile.ZIP_LZMA)
При работе с большими объёмами данных рекомендуется предварительно протестировать различные методы сжатия, чтобы найти оптимальный баланс между размером архива и временем его создания для вашего конкретного случая.
Практические сценарии применения zip-архивирования на Python
Zip-архивирование в Python находит применение в различных практических сценариях разработки и эксплуатации программного обеспечения. Рассмотрим наиболее распространенные случаи использования и готовые решения для них. 📊
1. Автоматизация резервного копирования
Регулярное создание резервных копий критически важных данных — одна из самых распространенных задач, которую можно решить с помощью zip-архивирования в Python:
import os
import zipfile
from datetime import datetime
import shutil
import schedule
import time
def backup_project(project_path, backup_dir):
"""Создает датированную резервную копию проекта"""
# Формируем имя архива с текущей датой и временем
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
archive_name = f"backup_{os.path.basename(project_path)}_{timestamp}"
# Создаем архив
backup_path = shutil.make_archive(
os.path.join(backup_dir, archive_name),
'zip',
os.path.dirname(project_path),
os.path.basename(project_path)
)
print(f"Создана резервная копия: {backup_path}")
# Удаляем старые резервные копии (оставляем только 5 последних)
cleanup_old_backups(backup_dir, 5)
def cleanup_old_backups(backup_dir, keep_count):
"""Удаляет старые резервные копии, оставляя только указанное количество"""
backup_files = [os.path.join(backup_dir, f) for f in os.listdir(backup_dir)
if f.startswith('backup_') and f.endswith('.zip')]
# Сортируем по времени создания файла (от старых к новым)
backup_files.sort(key=os.path.getctime)
# Удаляем старые файлы, оставляя только keep_count последних
for old_file in backup_files[:-keep_count]:
os.remove(old_file)
print(f"Удалена устаревшая резервная копия: {old_file}")
# Настройка ежедневного резервного копирования в полночь
schedule.every().day.at("00:00").do(
backup_project,
project_path='/path/to/project',
backup_dir='/path/to/backups'
)
# Запускаем цикл планировщика
while True:
schedule.run_pending()
time.sleep(60)
2. Подготовка данных для передачи
Архивирование данных перед отправкой по сети или через API:
import os
import zipfile
import requests
from io import BytesIO
def prepare_and_send_data(data_dir, api_endpoint, api_key):
"""Архивирует данные и отправляет их на удалённый сервер"""
# Создаем архив в памяти
memory_file = BytesIO()
with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, _, files in os.walk(data_dir):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, data_dir)
zipf.write(file_path, arcname)
# Перемещаем указатель в начало файла
memory_file.seek(0)
# Отправляем данные через API
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/zip'
}
response = requests.post(
api_endpoint,
headers=headers,
data=memory_file.read()
)
if response.status_code == 200:
print(f"Данные успешно отправлены, ответ сервера: {response.json()}")
else:
print(f"Ошибка при отправке данных: {response.status_code}, {response.text}")
# Использование
prepare_and_send_data(
data_dir='/path/to/data',
api_endpoint='https://api.example.com/upload',
api_key='your_api_key_here'
)
3. Упаковка и распространение приложений
Упаковка Python-приложений для распространения:
import os
import zipfile
import glob
def package_application(app_dir, output_path, version):
"""Создает дистрибутив приложения указанной версии"""
# Формируем имя архива с версией
archive_name = f"{os.path.basename(app_dir)}-v{version}.zip"
archive_path = os.path.join(output_path, archive_name)
with zipfile.ZipFile(archive_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
# Добавляем основные файлы приложения
for root, _, files in os.walk(app_dir):
# Исключаем директории с кешем, временными файлами и т.д.
if '__pycache__' in root or '.git' in root or 'venv' in root:
continue
for file in files:
# Исключаем файлы разработки и кеша
if file.endswith(('.pyc', '.pyo', '.tmp', '.log')) or file.startswith('.'):
continue
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, os.path.dirname(app_dir))
zipf.write(file_path, arcname)
# Добавляем README и LICENSE, если они есть
for doc_file in glob.glob(os.path.join(app_dir, '*.md')) + glob.glob(os.path.join(app_dir, 'LICENSE*')):
zipf.write(doc_file, os.path.basename(doc_file))
print(f"Создан дистрибутив приложения: {archive_path}")
return archive_path
# Использование
package_application(
app_dir='/path/to/my_application',
output_path='/path/to/releases',
version='1.2.0'
)
Приведенные сценарии показывают, насколько гибким может быть использование zip-архивирования в Python. В зависимости от конкретной задачи вы можете выбрать наиболее подходящий метод из рассмотренных в этой статье.
Для каждого практического сценария важно учитывать:
- Объем архивируемых данных и доступную память
- Необходимый уровень безопасности (требуется ли шифрование)
- Частоту выполнения операций архивирования
- Требования к степени сжатия и скорости операций
- Необходимость сохранения метаданных файлов (время создания, разрешения и т.д.)
Комбинируя различные методы архивирования и настраивая параметры сжатия, вы можете создать решение, оптимальное для ваших конкретных потребностей. 🚀
Работа с zip-архивами в Python предоставляет гибкие инструменты для решения широкого спектра задач по управлению файлами. Стандартные модули zipfile и shutil закрывают большинство повседневных сценариев, а специализированные библиотеки вроде pyzipper добавляют функциональность шифрования для защиты конфиденциальных данных. Выбирая подходящий метод создания архивов, вы оптимизируете не только размер данных, но и производительность ваших Python-приложений. Какую бы технику вы ни выбрали, грамотное архивирование директорий станет ценным инструментом в вашем арсенале разработчика.