Zipfile.ZipFile.write: примеры (PYTHON)

Использование функции write для добавления файлов в ZIP архив
Раздел: Архивы, Создание архивов
zipfile.ZipFile.write(filename, arcname, compress_type, compresslevel): None

Описание функции ZipFile.write

Функция zipfile.ZipFile.write() в модуле zipfile языка Python предназначена для добавления файлов в ZIP-архив. Ее использование актуально при программном создании или модификации архивов, автоматизации резервного копирования, упаковки ресурсов для распространения или сжатия данных перед передачей.

Сигнатура функции: ZipFile.write(filename, arcname=None, compress_type=None, compresslevel=None)

Аргументы функции

  • filename (str | os.PathLike): Путь к файлу, который необходимо добавить в архив. Это обязательный аргумент.
  • arcname (str | None): Имя файла внутри архива. Если аргумент не указан, файл будет добавлен с тем же именем, но без начальной части пути к общей директории. Позволяет переименовать файл в архиве или изменить его относительный путь.
  • compress_type (int | None): Метод сжатия. Если не указан, используется метод, заданный при создании объекта ZipFile. Возможные значения: zipfile.ZIP_STORED (без сжатия), zipfile.ZIP_DEFLATED (стандартное сжатие DEFLATE, требует наличия модуля zlib), zipfile.ZIP_BZIP2 (сжатие BZIP2, требует наличия модуля bz2), zipfile.ZIP_LZMA (сжатие LZMA, требует наличия модуля lzma).
  • compresslevel (int | None): Уровень сжатия для методов ZIP_DEFLATED и ZIP_BZIP2. Для ZIP_DEFLATED принимает значения от 0 до 9 (где 1 - самое быстрое, 9 - самое сильное сжатие). Для ZIP_BZIP2 - от 1 до 9. В версиях Python до 3.7 этот аргумент не поддерживался.

Возвращаемое значение

Функция не возвращает значения (None). Ее основное действие - запись файла в открытый ZIP-архив.

Простые примеры использования

Создание архива и добавление одного файла с именем по умолчанию.

import zipfile

with zipfile.ZipFile('archive.zip', 'w') as zf:
    zf.write('document.txt')
    print('Файл добавлен')
Файл добавлен

Добавление файла с изменением имени внутри архива.

import zipfile

with zipfile.ZipFile('archive.zip', 'w') as zf:
    zf.write('data.csv', arcname='2024/stats.csv')
# В архиве файл будет расположен как 2024/stats.csv

Использование различных методов сжатия.

import zipfile

with zipfile.ZipFile('archive.zip', 'w') as zf:
    # Без сжатия
    zf.write('file1.txt', compress_type=zipfile.ZIP_STORED)
    # Со сжатием DEFLATE (по умолчанию для режима 'w')
    zf.write('file2.txt', compress_type=zipfile.ZIP_DEFLATED)

Указание уровня сжатия для метода DEFLATE.

import zipfile

with zipfile.ZipFile('archive.zip', 'w') as zf:
    zf.write('large_file.bin', compress_type=zipfile.ZIP_DEFLATED, compresslevel=9)

Похожие функции в Python

  • zipfile.ZipFile.writestr(): Позволяет записать в архив данные из строки или бинарного объекта, а не из файла. Используется, когда данные уже находятся в памяти. Принимает аргументы zinfo_or_arcname (имя или объект ZipInfo) и data (данные для записи).
  • shutil.make_archive(): Функция высокоуровневого модуля shutil для создания архивов (ZIP, tar и др.). Она проще в использовании для архивации целых директорий, но предоставляет меньше контроля над отдельными файлами по сравнению с zipfile.
  • pathlib.Path.write_bytes() / write_text() в комбинации с zipfile: Не являются прямой альтернативой, но могут использоваться для создания содержимого файлов перед добавлением в архив.

Выбор зависит от задачи: для точного контроля над процессом добавления файлов в ZIP-архив, включая управление метаданными и сжатием, применяется ZipFile.write(). Для упаковки строковых данных подходит writestr(). Для быстрого создания архива всей директории удобна функция shutil.make_archive().

Аналоги в других языках программирования

Java (java.util.zip.ZipOutputStream)

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("archive.zip"))) {
            ZipEntry entry = new ZipEntry("file.txt");
            zos.putNextEntry(entry);
            byte[] bytes = Files.readAllBytes(Paths.get("file.txt"));
            zos.write(bytes, 0, bytes.length);
            zos.closeEntry();
        }
    }
}

В Java требуется вручную создавать объекты ZipEntry и управлять потоками байтов.

JavaScript (Node.js с модулем 'archiver' или 'jszip')

// Использование библиотеки JSZip
const JSZip = require('jszip');
const fs = require('fs');

const zip = new JSZip();
zip.file("hello.txt", "Hello World\n");
zip.generateNodeStream({type:'nodebuffer',streamFiles:true})
   .pipe(fs.createWriteStream('archive.zip'))
   .on('finish', () => { console.log('Архив создан'); });

В JavaScript, особенно в браузере, для работы с ZIP используются сторонние библиотеки, так как нативная поддержка отсутствует.

C# (System.IO.Compression.ZipFile)

using System.IO.Compression;

class Program {
    static void Main() {
        using (ZipArchive archive = ZipFile.Open("archive.zip", ZipArchiveMode.Create)) {
            archive.CreateEntryFromFile("data.txt", "data.txt");
        }
    }
}

В C# в пространстве имен System.IO.Compression есть высокоуровневый метод CreateEntryFromFile, аналогичный по простоте.

PHP (ZipArchive::addFile)

$zip = new ZipArchive();
if ($zip->open('archive.zip', ZipArchive::CREATE) === TRUE) {
    $zip->addFile('file.txt', 'file.txt');
    $zip->close();
    echo 'Файл добавлен';
} else {
    echo 'Ошибка';
}

Синтаксис и логика в PHP очень близки к Python, используются методы объекта ZipArchive.

Распространенные ошибки

Добавление несуществующего файла приводит к исключению FileNotFoundError.

import zipfile

try:
    with zipfile.ZipFile('test.zip', 'w') as zf:
        zf.write('missing_file.txt')
except FileNotFoundError as e:
    print(f'Ошибка: {e}')
Ошибка: [Errno 2] No such file or directory: 'missing_file.txt'

Попытка записи в архив, открытый в режиме чтения ('r').

import zipfile

with zipfile.ZipFile('archive.zip', 'r') as zf: # Открыт для чтения
    zf.write('new.txt')  # Ошибка
ValueError: Attempt to write to ZIP archive that was opened for reading

Использование неподдерживаемого метода сжатия при отсутствии соответствующего модуля.

import zipfile

try:
    with zipfile.ZipFile('test.zip', 'w', compression=zipfile.ZIP_BZIP2) as zf:
        zf.write('file.txt')
except RuntimeError as e:
    print(f'Требуется модуль: {e}')
Требуется модуль: bz2 module is not available

Ошибки, связанные с некорректными путями в аргументе arcname, например, использование абсолютного пути, который может привести к неожиданной структуре архива.

Изменения в последних версиях Python

  • Python 3.4: Добавлена поддержка объектов, реализующих интерфейс os.PathLike, для аргументов filename и arcname.
  • Python 3.6: Добавлен параметр compresslevel для контроля уровня сжатия. В более ранних версиях этот параметр передавался через ZipFile конструктор.
  • Python 3.7: Параметр compresslevel стал доступен непосредственно в методе write(), что позволило задавать разный уровень сжатия для отдельных файлов в одном архиве.
  • Python 3.8: Добавлена поддержка сжатия LZMA через константу zipfile.ZIP_LZMA при наличии модуля lzma.

Расширенные примеры применения

Добавление всех файлов из директории с сохранением структуры поддиректорий.

Пример python
import zipfile
import os

def add_folder_to_zip(zipf, folder, arcname=''):
    for root, dirs, files in os.walk(folder):
        for file in files:
            full_path = os.path.join(root, file)
            # Создаем относительный путь для архива
            rel_path = os.path.relpath(full_path, folder)
            zipf.write(full_path, os.path.join(arcname, rel_path))

with zipfile.ZipFile('project.zip', 'w') as zf:
    add_folder_to_zip(zf, 'my_project')

Фильтрация файлов по расширению перед добавлением.

Пример python
import zipfile
import os

with zipfile.ZipFile('images.zip', 'w') as zf:
    for file in os.listdir('.'):
        if file.endswith(('.png', '.jpg', '.jpeg')):
            zf.write(file)
            print(f'Добавлен: {file}')

Добавление файла с использованием объекта ZipInfo для точного контроля метаданных (времени изменения, прав доступа).

Пример python
import zipfile
import time
import os

with zipfile.ZipFile('with_meta.zip', 'w') as zf:
    file_name = 'script.py'
    stat = os.stat(file_name)
    # Создание объекта ZipInfo
    zip_info = zipfile.ZipInfo.from_file(file_name)
    zip_info.compress_type = zipfile.ZIP_DEFLATED
    # Установка времени модификации
    zip_info.date_time = time.localtime(stat.st_mtime)[:6]
    # Установка прав доступа (Unix-атрибуты)
    zip_info.external_attr = (stat.st_mode & 0xFFFF) << 16
    with open(file_name, 'rb') as f:
        zf.writestr(zip_info, f.read())

Постепенное добавление файлов в архив с обработкой больших объемов данных.

Пример python
import zipfile

def write_large_file_in_chunks(zipf, source_path, arcname, chunk_size=8192):
    with open(source_path, 'rb') as src:
        with zipf.open(arcname, 'w', force_zip64=True) as dest:
            while chunk := src.read(chunk_size):
                dest.write(chunk)

with zipfile.ZipFile('large.zip', 'w', allowZip64=True) as zf:
    write_large_file_in_chunks(zf, 'huge_video.mkv', 'video.mkv')

Создание архива с разными методами сжатия для разных типов файлов.

Пример python
import zipfile
import os

compression_map = {
    '.txt': zipfile.ZIP_DEFLATED,
    '.log': zipfile.ZIP_DEFLATED,
    '.png': zipfile.ZIP_STORED,  # Изображения уже сжаты
    '.zip': zipfile.ZIP_STORED   // Архивы уже сжаты
}

with zipfile.ZipFile('mixed.zip', 'w') as zf:
    for file in os.listdir('.'):
        if os.path.isfile(file):
            ext = os.path.splitext(file)[1].lower()
            compress_type = compression_map.get(ext, zipfile.ZIP_DEFLATED)
            zf.write(file, compress_type=compress_type, compresslevel=6)

питон zipfile.ZipFile.write function comments

En
Zipfile.ZipFile.write Write file to ZIP archive