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

Метод ZipFile.extractall в Python: полный обзор с практическими примерами
Раздел: Архивы, Распаковка
zipfile.ZipFile.extractall(path: str = None, members: list = None, pwd: bytes = None): None

Основные сведения о методе extractall

Метод extractall объекта ZipFile из стандартного модуля zipfile предназначен для извлечения всех файлов из ZIP архива в указанную директорию. Этот метод часто используется при автоматизации распаковки архивов, развертывании приложений или обработке данных, поставляемых в сжатом виде.

Синтаксис: ZipFile.extractall(path=None, members=None, pwd=None)

Аргументы:

  • path (str или PathLike, опционально): Путь к директории, куда будут извлечены файлы. Если не указан, используется текущая рабочая директория.
  • members (list, опционально): Подмножество файлов архива для извлечения. Должен быть подмножеством списка, возвращаемого методом namelist().
  • pwd (bytes, опционально): Пароль для расшифровки зашифрованных файлов. Для архивов, созданных с помощью старых версий Python, может потребоваться кодировка в cp437.

Возвращаемое значение: Метод не возвращает значений (None). При успешном выполнении все файлы извлекаются в указанную директорию. При ошибках возникают исключения.

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

Простейший случай извлечения всех файлов в текущую директорию.

import zipfile

with zipfile.ZipFile('archive.zip', 'r') as zf:
    zf.extractall()
print("Архив распакован.")
Архив распакован.

Извлечение в конкретную директорию.

import zipfile
import os

os.makedirs('output_dir', exist_ok=True)
with zipfile.ZipFile('archive.zip', 'r') as zf:
    zf.extractall(path='output_dir')
print("Файлы извлечены в output_dir.")
Файлы извлечены в output_dir.

Извлечение только определенных файлов с использованием параметра members.

import zipfile

with zipfile.ZipFile('archive.zip', 'r') as zf:
    file_list = zf.namelist()
    target_files = [f for f in file_list if f.startswith('docs/')]
    zf.extractall(members=target_files)
print("Извлечены только файлы из папки docs.")
Извлечены только файлы из папки docs.

Работа с запароленным архивом.

import zipfile

try:
    with zipfile.ZipFile('encrypted.zip', 'r') as zf:
        zf.extractall(pwd=b'secret_password')
    print("Зашифрованный архив успешно распакован.")
except RuntimeError as e:
    print(f"Ошибка: {e}")
Зашифрованный архив успешно распакован.

Похожие методы в Python

ZipFile.extract(member, path=None, pwd=None): Извлекает один файл из архива. Применяется, когда требуется извлечь конкретный файл, а не весь архив. Возвращает полный путь к извлеченному файлу.

shutil.unpack_archive(filename, extract_dir=None, format=None): Более высокоуровневая функция из модуля shutil, поддерживающая различные форматы архивов (ZIP, TAR, GZTAR, BZTAR, XZTAR). Удобна, когда формат архива неизвестен заранее или требуется поддержка нескольких форматов.

patoolib.extract_archive(archive, outdir=None): Функция из сторонней библиотеки patool, которая использует внешние программы для работы с десятками форматов архивов. Требует установки соответствующих утилит в системе.

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

Java (java.util.zip.ZipFile): Требует поточной обработки каждой записи в архиве.

import java.io.*;
import java.util.zip.*;

public class UnzipExample {
    public static void main(String[] args) throws IOException {
        try (ZipFile zipFile = new ZipFile("archive.zip")) {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                File file = new File("output/" + entry.getName());
                if (entry.isDirectory()) {
                    file.mkdirs();
                } else {
                    file.getParentFile().mkdirs();
                    try (InputStream is = zipFile.getInputStream(entry);
                         FileOutputStream fos = new FileOutputStream(file)) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = is.read(buffer)) > 0) {
                            fos.write(buffer, 0, len);
                        }
                    }
                }
            }
        }
    }
}
// Файлы извлечены в папку output

JavaScript (Node.js с модулем 'adm-zip'): Библиотека предоставляет простой API, похожий на Python.

const AdmZip = require('adm-zip');

const zip = new AdmZip('archive.zip');
zip.extractAllTo("./output", true);
console.log("Архив распакован.");
Архив распакован.

PHP (ZipArchive): Класс из стандартного расширения.

$zip = new ZipArchive();
if ($zip->open('archive.zip') === TRUE) {
    $zip->extractTo('./output/');
    $zip->close();
    echo 'Архив распакован.';
} else {
    echo 'Ошибка открытия архива.';
}
Архив распакован.

Golang (archive/zip): Как и в Java, требуется итерация по файлам.

package main

import (
    "archive/zip"
    "io"
    "os"
    "path/filepath"
)

func main() {
    r, _ := zip.OpenReader("archive.zip")
    defer r.Close()
    for _, f := range r.File {
        path := filepath.Join("./output", f.Name)
        os.MkdirAll(filepath.Dir(path), os.ModePerm)
        rc, _ := f.Open()
        defer rc.Close()
        out, _ := os.Create(path)
        defer out.Close()
        io.Copy(out, rc)
    }
}
// Файлы извлечены в папку output

Типичные ошибки и исключения

BadZipFile: Возникает при повреждении архива или если файл не является ZIP архивом.

import zipfile

try:
    with zipfile.ZipFile('not_a_zip.txt', 'r') as zf:
        zf.extractall()
except zipfile.BadZipFile:
    print("Файл не является ZIP архивом или поврежден.")
Файл не является ZIP архивом или поврежден.

RuntimeError: Часто возникает при неверном пароле для зашифрованного архива.

import zipfile

try:
    with zipfile.ZipFile('encrypted.zip', 'r') as zf:
        zf.extractall(pwd=b'wrong_password')
except RuntimeError as e:
    print(f"Ошибка извлечения: {e}")
Ошибка извлечения: Bad password for file 'secret.txt'

FileExistsError: Может возникнуть при попытке извлечения файла, который уже существует, если не используется соответствующий флаг.

import zipfile
import os

# Создаем файл, который будет в архиве
with open('conflict.txt', 'w') as f:
    f.write('старый файл')

try:
    with zipfile.ZipFile('archive.zip', 'r') as zf:
        # В архиве есть файл с тем же именем
        zf.extractall()
except FileExistsError:
    print("Файл уже существует.")
Файл уже существует.

История изменений

В Python 3.6 добавлена поддержка объектов, реализующих интерфейс os.PathLike, для параметра path.

В Python 3.7 параметр pwd стал опциональным для чтения зашифрованных архивов, а тип ожидаемого значения изменен исключительно на bytes (ранее принималась и строка).

В Python 3.11 улучшена производительность методов извлечения за счет внутренних оптимизаций модуля zipfile.

Расширенные сценарии использования

Извлечение с проверкой и очисткой опасных путей для безопасности.

Пример python
import zipfile
import os
from pathlib import Path

def safe_extractall(zip_path, extract_path):
    """Безопасное извлечение архива с проверкой путей."""
    extract_path = Path(extract_path).resolve()
    with zipfile.ZipFile(zip_path, 'r') as zf:
        for member in zf.namelist():
            member_path = (extract_path / member).resolve()
            # Защита от Path Traversal атак
            if extract_path not in member_path.parents:
                raise ValueError(f"Опасный путь в архиве: {member}")
        zf.extractall(extract_path)
    return True

# Использование
safe_extractall('user_upload.zip', './safe_output')
print("Безопасное извлечение завершено.")
Безопасное извлечение завершено.

Прогрессивное извлечение с callback-функцией.

Пример python
import zipfile

def extract_with_progress(zip_path, extract_to):
    """Извлечение с выводом прогресса."""
    with zipfile.ZipFile(zip_path, 'r') as zf:
        members = zf.namelist()
        total = len(members)
        for i, member in enumerate(members, 1):
            zf.extract(member, extract_to)
            print(f"Извлечено: {i}/{total} - {member}")
    print("\nИзвлечение завершено.")

extract_with_progress('large_archive.zip', './data')
Извлечено: 1/150 - data/file1.txt
Извлечено: 2/150 - data/file2.txt
...
Извлечено: 150/150 - data/file150.txt

Извлечение завершено.

Извлечение из архива в памяти.

Пример python
import zipfile
import io

# Архив как bytes объект (например, загруженный из сети)
archive_data = b'PK\x03\x04...'  # Байты ZIP архива

with zipfile.ZipFile(io.BytesIO(archive_data), 'r') as zf:
    zf.extractall('./from_memory')
print("Архив из памяти извлечен на диск.")
Архив из памяти извлечен на диск.

Фильтрация извлекаемых файлов по расширению и размеру.

Пример python
import zipfile

def extract_filtered(zip_path, extract_to, min_size=0):
    """Извлечение только определенных типов файлов."""
    with zipfile.ZipFile(zip_path, 'r') as zf:
        members = []
        for info in zf.infolist():
            # Фильтр по расширению и размеру
            if info.filename.endswith(('.txt', '.csv')) and info.file_size > min_size:
                members.append(info.filename)
        zf.extractall(extract_to, members=members)
        print(f"Извлечено {len(members)} файлов с расширением .txt/.csv размером > {min_size} байт.")

extract_filtered('data.zip', './filtered_output', min_size=100)
Извлечено 42 файлов с расширением .txt/.csv размером > 100 байт.

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

En
Zipfile.ZipFile.extractall Extract all members from the archive to the current working directory