Tarfile.open: примеры (PYTHON)
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.gzJava: Часто используется библиотека 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 архивами.
Расширенные примеры использования
Извлечение конкретного файла из архива в память.
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",Создание архива с фильтрацией файлов по расширению.
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 для архивирования символических ссылок.
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
Чтение большого архива по частям для экономии памяти.
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 байт
Создание архива с пользовательскими метаданными для файлов.
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 и заданные метаданные