Tarfile.open: примеры (PYTHON)

Функция tarfile.open для работы с tar архивами
Раздел: Архивы, Работа с файлами
tarfile.open(name: str or path-like, mode: str = 'r', fileobj: file object = None, ...): tarfile.TarFile

Описание функции tarfile.open

Модуль tarfile в Python предоставляет функциональность для чтения и записи tar архивов. Функция tarfile.open() является основным способом создания объекта TarFile.

Функция обычно используется, когда требуется создать, извлечь или добавить файлы в архив формата tar, включая его сжатые варианты (.tar.gz, .tar.bz2, .tar.xz).

Сигнатура функции: tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)

Аргументы:

  • name (str или путь): Имя файла архива. Если указан fileobj, может быть строкой для указания режима.
  • mode (str): Режим открытия архива. Комбинация из символов: 'r', 'w', 'a', 'x' для чтения, записи, добавления и исключительного создания; и опционально ':' или '|' с указанием формата сжатия: 'gz', 'bz2', 'xz' (например, 'r:gz').
  • fileobj (файловый объект): Если указан, функция будет использовать этот объект вместо открытия файла по имени. Должен поддерживать методы read(), write(), seek(), tell().
  • bufsize (int): Размер буфера для операций с архивом. По умолчанию 10240 байт.
  • **kwargs: Дополнительные аргументы, передаваемые в конструктор TarFile (например, format, dereference, ignore_zeros).

Возвращаемое значение: Объект класса TarFile, представляющий открытый архив. Этот объект предоставляет методы для работы с содержимым архива (extractall, extract, add, getnames и др.).

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

Открытие существующего архива для чтения.

import tarfile

# Чтение обычного tar архива
with tarfile.open('archive.tar', 'r') as tar:
    print(tar.getnames())
['file1.txt', 'folder/', 'folder/file2.txt']

Создание нового сжатого архива.

import tarfile

# Создание архива с gzip сжатием
with tarfile.open('project.tar.gz', 'w:gz') as tar:
    tar.add('script.py', arcname='scripts/script.py')
print("Архив создан")
Архив создан

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

import tarfile

# Добавление файла в архив (режим 'a' не поддерживает сжатие)
with tarfile.open('archive.tar', 'a') as tar:
    tar.add('new_data.csv')
print("Файл добавлен")
Файл добавлен

Открытие архива из файлового объекта.

import tarfile, io

# Создание архива в памяти
buffer = io.BytesIO()
with tarfile.open(fileobj=buffer, mode='w') as tar:
    tarinfo = tarfile.TarInfo('note.txt')
    data = b"Some text"
    tarinfo.size = len(data)
    tar.addfile(tarinfo, io.BytesIO(data))

# Чтение из того же буфера
buffer.seek(0)
with tarfile.open(fileobj=buffer, mode='r') as tar:
    print([m.name for m in tar.getmembers()])
['note.txt']

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

Модуль shutil предоставляет высокоуровневые функции для работы с архивами. Функция shutil.make_archive создает архив из директории, а shutil.unpack_archive извлекает его.

import shutil
shutil.make_archive('backup', 'gztar', root_dir='my_folder')
# Создает backup.tar.gz

Функции из модуля shutil проще в использовании для стандартных задач, но менее гибкие. tarfile.open дает полный контроль над процессом архивации, метаданными и сжатием.

Для работы с ZIP архивами используется модуль zipfile и его функция zipfile.ZipFile. Этот формат более распространен в системах Windows и для Java архивов.

Альтернативы в других языках

PHP: Используются функции PharData (для tar) или расширения вроде tar через команды exec.

// Создание tar архива
$phar = new PharData('project.tar');
$phar->addFile('index.php');
// Сжатие
$phar->compress(Phar::GZ); // Создает project.tar.gz

Java: Часто используется библиотека Apache Commons Compress.

// Чтение tar.gz архива с помощью Apache Commons Compress
import org.apache.commons.compress.archivers.tar.*;
import org.apache.commons.compress.compressors.gzip.*;

try (TarArchiveInputStream tarInput = new TarArchiveInputStream(
        new GzipCompressorInputStream(new FileInputStream("archive.tar.gz")))) {
    TarArchiveEntry entry;
    while ((entry = tarInput.getNextTarEntry()) != null) {
        System.out.println(entry.getName());
    }
}

JavaScript/Node.js: Популярен пакет tar из npm.

const tar = require('tar');
tar.c({
  gzip: true,
  file: 'archive.tar.gz'
}, ['file1.js', 'folder']).then(() => {
  console.log('Архив создан');
});

Go: Пакет archive/tar из стандартной библиотеки.

import "archive/tar"
// Создание заголовка и запись файла в архив
hdr := &tar.Header{
    Name: "readme.txt",
    Size: int64(len(data)),
}
tw := tar.NewWriter(outputFile)
tw.WriteHeader(hdr)
tw.Write([]byte(data))
tw.Close()

Типичные ошибки

Ошибка при попытке открыть несуществующий архив в режиме чтения.

import tarfile
try:
    with tarfile.open('missing.tar', 'r') as tar:
        pass
except FileNotFoundError as e:
    print(f"Ошибка: {e}")
Ошибка: [Errno 2] No such file or directory: 'missing.tar'

Неподдерживаемый режим сжатия.

import tarfile
try:
    with tarfile.open('test.tar', 'r:zzz') as tar:
        pass
except tarfile.CompressionError as e:
    print(f"Ошибка сжатия: {e}")
Ошибка сжатия: compression mode zzz is not supported

Попытка добавления файлов в архив, открытый в режиме чтения.

import tarfile
with tarfile.open('archive.tar', 'r') as tar:
    try:
        tar.add('new.txt')  # TarFile не разрешает запись в режиме 'r'
    except tarfile.ReadError as e:
        print(f"Ошибка: {e}")
Ошибка: cannot add file 'new.txt' to a tar archive opened for reading

Использование режима добавления 'a' со сжатием.

import tarfile
try:
    with tarfile.open('archive.tar.gz', 'a:gz') as tar:
        tar.add('file.txt')
except tarfile.CompressionError as e:
    print(f"Ошибка: Режим 'a' не поддерживает сжатие")
Ошибка: Режим 'a' не поддерживает сжатие

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

В Python 3.8 была добавлена поддержка формата сжатия 'x' (lzma) по умолчанию, если модуль lzma доступен.

В Python 3.12 улучшена обработка ошибок при работе с битыми архивами. Уточнено поведение при встрече с нулевыми блоками в зависимости от значения аргумента ignore_zeros.

В версии 3.9 были обновлены и задокументированы ограничения на использование режима добавления 'a' вместе с параметрами сжатия. Этот режим работает только с несжатыми tar архивами.

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

Извлечение конкретного файла из архива в память.

Пример python
import tarfile, io

with tarfile.open('data.tar.xz', 'r:xz') as tar:
    # Получение информации о файле
    member = tar.getmember('config/settings.json')
    # Извлечение содержимого файла как bytes
    f = tar.extractfile(member)
    if f:
        content = f.read()
        print(f"Размер файла: {len(content)} байт")
        # Декодирование, если это текст
        text = content.decode('utf-8')
        print(text[:100])
Размер файла: 1254 байт
{
  "app_name": "Example",
  "version": 1.0,
  "settings": {
    "theme": "dark",

Создание архива с фильтрацией файлов по расширению.

Пример python
import tarfile, os

def filter_py_files(tarinfo):
    if tarinfo.name.endswith('.py'):
        print(f"Добавляется: {tarinfo.name}")
        return tarinfo
    else:
        return None

with tarfile.open('src_backup.tar.gz', 'w:gz') as tar:
    tar.add('my_project', arcname='src', filter=filter_py_files)
Добавляется: src/utils.py
Добавляется: src/main.py

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

Пример python
import tarfile, os
# Создаем символическую ссылку для примера
if not os.path.exists('link_to_data'):
    os.symlink('./real_data.txt', 'link_to_data')

# Без dereference - сохраняется как ссылка
with tarfile.open('with_link.tar', 'w') as tar:
    tar.add('link_to_data')
    for m in tar.getmembers():
        print(f"{m.name} - islnk: {m.islnk()}")
link_to_data - islnk: True

Чтение большого архива по частям для экономии памяти.

Пример python
import tarfile

with tarfile.open('large_logs.tar.bz2', 'r:bz2') as tar:
    for member in tar:
        if member.isfile() and member.size > 0:
            print(f"Обработка {member.name} ({member.size} байт)")
            # Извлекаем файл по частям
            f = tar.extractfile(member)
            chunk_size = 8192
            total_read = 0
            while chunk := f.read(chunk_size):
                total_read += len(chunk)
                # Обработка чанка данных
                pass
            print(f"Прочитано {total_read} байт")
Обработка logs/app.log (1048576 байт)
Прочитано 1048576 байт
Обработка logs/system.log (524288 байт)
Прочитано 524288 байт

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

Пример python
import tarfile, os, time
from stat import S_IRUSR, S_IWUSR, S_IXUSR

with tarfile.open('custom_meta.tar', 'w') as tar:
    filename = 'script.sh'
    tarinfo = tarfile.TarInfo(name=filename)
    # Установка прав доступа (rwx------)
    tarinfo.mode = S_IRUSR | S_IWUSR | S_IXUSR
    tarinfo.mtime = time.time()  # Текущее время
    tarinfo.uid = 1000
    tarinfo.gid = 1000
    tarinfo.uname = 'user'
    tarinfo.gname = 'users'
    
    with open(filename, 'rb') as f:
        tarinfo.size = os.path.getsize(filename)
        tar.addfile(tarinfo, f)
    
    # Проверка
    tar.members[0].mode == 0o700  # True в восьмеричной системе
# В архиве файл script.sh будет иметь права 700 и заданные метаданные

питон tarfile.open function comments

En
Tarfile.open Open a tar archive