Сообщить об ошибке.

Методы объекта TarFile модуля tarfile в Python

Использование объекта TarFile

В данном разделе рассмотрены методы объекта TarFile с их подробным описанием и примерами.

Объект TarFile получается в результате чтения или записи архивов tar, tar.gz, tar.bz2 или tar.xz функцией tarfile.open() или создания экземпляра класса 'tarfile.TarFile()'.

Содержание:


tarfile.TarFile.open(...):

Метод класса tarfile.TarFile.open() представляет альтернативный конструктор. Функция tarfile.open() на самом деле является ссылкой на этот метод класса.

import tarfile

# архивируемый каталог
path = '/home/docs-python/script/sql-script/'
# корневой путь в архиве
path_tar = 'sql-script'

with tarfile.TarFile.open('sample.tar.bz2', 'w:bz2') as tar:
    tar.add(path, path_tar)
    
with tarfile.TarFile.open('sample.tar.bz2') as tar:
    infos = tar.getmembers()
    for inf in infos:
        print(inf.name)

# sql-script
# sql-script/Script-5.sql
# sql-script/Script-1.sql
# sql-script/Script-3.sql
# sql-script/procedure.sql
# sql-script/Script-2.sql
# sql-script/Script-4.sql

TarFile.getmember(name):

Метод TarFile.getmember() возвращает объект TarInfo для имени name элемента в архиве. Если имя не может быть найдено в архиве, то появляется исключение KeyError.

import tarfile, time
    
with tarfile.open('sample.tar.bz2') as tar:
    info = tar.getmember('sql-script/Script-3.sql')
    str_time = time.strftime('%d.%m.%Y %H:%M', time.localtime(inf.mtime))
    print(f'{inf.size}\t{str_time}\t{inf.uname}')

# 1163    14.09.2019 08:06        docs-python

Примечание.

  • Если элемент встречается в архиве более одного раза, предполагается, что его последнее вхождение является самой последней версией.

TarFile.getmembers():

Метод TarFile.getmembers() возвращает члены архива в виде списка объектов TarInfo. Список имеет тот же порядок, что и файлы в архиве.

import tarfile, time, os
    
with tarfile.open('sample.tar.bz2') as tar:
    for inf in tar.getmembers():
        str_time = time.strftime('%d.%m.%Y %H:%M', time.localtime(inf.mtime))
        print(f'{inf.size}\t{str_time}\t{inf.name}')

# 0       18.05.2020 14:33        sql-script
# 2687    14.09.2019 08:07        sql-script/Script-5.sql
# 1371    14.09.2019 08:06        sql-script/Script-1.sql
# 50      14.09.2019 08:00        sql-script/Script-3.sql
# 37      14.09.2019 23:39        sql-script/.directory
# 3394    14.09.2019 08:07        sql-script/procedure.sql
# 1130    14.09.2019 08:06        sql-script/Script-2.sql
# 1163    14.09.2019 08:06        sql-script/Script-4.sql

TarFile.getnames():

Метод TarFile.getnames() возвращает члены архива в виде списка их имен. Он имеет тот же порядок, что и список, возвращаемый TarFile.getmembers().

import tarfile

with tarfile.open('sample.tar.bz2') as tar:
    for name in tar.getnames():
        print(name)

# sql-script
# sql-script/Script-5.sql
# sql-script/Script-1.sql
# sql-script/Script-3.sql
# sql-script/procedure.sql
# sql-script/Script-2.sql
# sql-script/Script-4.sql

TarFile.list(verbose=True, *, members=None):

Метод TarFile.list() печатает оглавление архива в sys.stdout.

Если аргумент verbose=False, то печатаются только имена членов архива. Если verbose=True, то выводится аналогично ls -l. Если заданы необязательный аргумент members, это должен быть список подмножества, возвращаемого TarFile.getmembers().

import tarfile

with tarfile.open('sample.tar.bz2') as tar:
    head = tar.list()
    print(head)

# ?rwxrwxr-x docs-python/docs-python          0 2020-05-18 14:33:18 sql-script/ 
# ?rw-rw-r-- docs-python/docs-python       2687 2019-09-14 08:07:18 sql-script/Script-5.sql 
# ?rw-rw-r-- docs-python/docs-python       1371 2019-09-14 08:06:38 sql-script/Script-1.sql 
# ?rw-rw-r-- docs-python/docs-python         50 2019-09-14 08:00:46 sql-script/Script-3.sql 
# ?rw------- docs-python/docs-python         37 2019-09-14 23:39:43 sql-script/.directory 
# ?rw-rw-r-- docs-python/docs-python       3394 2019-09-14 08:07:34 sql-script/procedure.sql 
# ?rw-rw-r-- docs-python/docs-python       1130 2019-09-14 08:06:30 sql-script/Script-2.sql 
# ?rw-rw-r-- docs-python/docs-python       1163 2019-09-14 08:06:31 sql-script/Script-4.sql

TarFile.next():

Метод TarFile.next() возвращает следующий элемент архива как объект TarInfo, когда объект TarFile открыт для чтения. Возвращает None, если все элемента архива исчерпаны.

import tarfile

with tarfile.open('sample.tar.bz2') as tar:
    print(tar.next().name)
    print(tar.next().name)
    print(tar.next().name)

# sql-script
# sql-script/Script-5.sql
# sql-script/Script-1.sql

TarFile.extractall(path=".", members=None, *, numeric_owner=False, filter=None):

Метод TarFile.extractall() извлекает все члены из архива в текущий рабочий каталог или путь к каталогу path.

Если задан необязательный аргумент members, то это должен быть список подмножества, возвращаемого TarFile.getmembers().

Информация каталога, такая как владелец, время модификации и разрешения, устанавливаются после извлечения всех участников. Это сделано для решения двух проблем: время изменения каталога сбрасывается каждый раз, когда в нем создается файл и если разрешения каталога не позволяют писать, извлечение файлов в него не удастся.

Если numeric_owner=True, то для извлеченных файлов числа uid и gid из tar-файла используются для установки владельца/группы. В противном случае используются именованные значения из tar-файла.

Изменено в Python 3.12: Добавлен аргумент filter.

Аргумент filter указывает, как элементы изменяются или отклоняются перед извлечением. Подробности в разделе "Фильтры извлечения...". Рекомендуется указать его явно в зависимости от того, какие функции tar необходимо поддерживать.

import tarfile, glob, os

path = 'extract_tar'
with tarfile.open('sample.tar.bz2', 'r') as tar:
    tar.extractall(path)

# смотрим файлы в каталоге 'extract_tar'
path = os.path.join(path, '**')
for file in glob.glob(path, recursive=True):
    print(file)

# extract_tar/
# extract_tar/sql-script
# extract_tar/sql-script/Script-5.sql
# extract_tar/sql-script/Script-1.sql
# extract_tar/sql-script/Script-3.sql
# extract_tar/sql-script/procedure.sql
# extract_tar/sql-script/Script-2.sql
# extract_tar/sql-script/Script-4.sql

Предупреждение.

  • Никогда не извлекайте архивы из ненадежных источников без предварительной проверки. Возможно, что файлы создаются вне пути, например, Члены, которые имеют абсолютные имена файлов, начинающиеся с '/' или имена файлов с двумя точками '..'.

TarFile.extract(member, path="", set_attrs=True, *, numeric_owner=False, filter=None):

Метод TarFile.extract() извлекает элемент, указанный в member из архива в текущий рабочий каталог, используя его полное имя. Информация о его файле извлекается максимально точно.

Элементом member может быть имя файла или объект TarInfo. Можно указать другой каталог для извлечения, передавая путь в аргумент path.

Путь path может быть похожим на путь объектом. Атрибуты файла (owner, mtime, mode) устанавливаются, если set_attrs не имеет значения False.

Если numeric_owner=True, то для извлеченных файлов числа uid и gid из tar-файла используются для установки владельца/группы. В противном случае используются именованные значения из tar-файла.

Изменено в Python 3.12: Добавлен аргумент filter.

Аргумент filter указывает, как элементы изменяются или отклоняются перед извлечением. Подробности в разделе "Фильтры извлечения...". Рекомендуется указать его явно в зависимости от того, какие функции tar необходимо поддерживать.

import tarfile, fnmatch, glob, os

# директория для извлечения
path = 'extract_tar'
# паттерн для извлечения файлов
file_pattern = '*[1-3].sql'
with tarfile.open('sample.tar.bz2', 'r') as tar:
    for inf in tar.getmembers():
        # выбираем файлы для извлечения по 'file_pattern'
        if fnmatch.fnmatch(inf.name, file_pattern):
            tar.extract(inf.name, path)

# смотрим файлы в каталоге 'extract_tar'
path = os.path.join(path, '**')
for file in glob.glob(path, recursive=True):
    print(file)

# extract_tar/
# extract_tar/sql-script
# extract_tar/sql-script/Script-1.sql
# extract_tar/sql-script/Script-3.sql
# extract_tar/sql-script/Script-2.sql

Примечание.

  • Метод TarFile.extract() не решает несколько проблем извлечения. В большинстве случаев вам следует рассмотреть возможность использования метода TarFile.extractall().

Предупреждение: смотрите предупреждение для TarFile.extractall().

TarFile.extractfile(member):

Метод TarFile.extractfile() извлекает элемент member из архива как объект файла.

Элемент member может быть именем файла или объектом TarInfo. Если member это обычный файл или ссылка, то возвращается объект io.BufferedReader. В противном случае возвращается None.

import tarfile

with tarfile.open('sample.tar.bz2', 'r') as tar:
    obj = tar.extractfile('sql-script/Script-5.sql')
    if obj is not None:
        byte = obj.read()
        print(byte.decode('utf-8'))

# SELECT name FROM city;
# SELECT street, number FROM address;

TarFile.errorlevel:

Атрибут TarFile.errorlevel представляет собой уровень ошибок при извлечении архива.

Если TarFile.errorlevel равен 0, то при использовании TarFile.extract() и TarFile.extractall() ошибки игнорируются. Тем не менее, когда значение debug больше 0, они отображаются как сообщения об ошибках в выходных данных отладки. Если значение равно 1 (по умолчанию), то все фатальные ошибки генерируются как исключения OSError или FilterError. Если 2, то все неустранимые ошибки также генерируются как исключения TarError.

Всегда возникают некоторые исключения, например, вызванные неправильными типами аргументов или повреждением данных.

Пользовательские фильтры извлечения должны вызывать FilterError для фатальных ошибок и ExtractError для не фатальных.

TarFile.extraction_filter:

Новое в версии 3.12.

Атрибут TarFile.extraction_filter представляет собой фильтр извлечения, используемый по умолчанию для аргумента filter методов TarFile.extract() и TarFile.extractall().

Атрибут может иметь значение None или быть вызываемым. Для этого атрибута не допускаются строковые имена, в отличие от аргумента filter для TarFile.extract()

Если значение TarFile.extraction_filter равно None (по умолчанию), то вызов метода извлечения без аргумента filter вызовет предупреждение DeprecationWarning и возврат к фильтру 'fully_trusted', опасное поведение которого соответствует предыдущим версиям Python.

В Python 3.14+, если оставить TarFile.extraction_filter=None, то по умолчанию методы извлечения будут использовать фильтр 'data'.

Атрибут может быть установлен в экземплярах или переопределен в подклассах. Также можно установить его в самом классе TarFile, что установит глобальное значение по умолчанию и повлияет на все виды использования модуля tarfile. Рекомендуется делать это только в приложениях верхнего уровня или конфигурации сайта. Чтобы таким образом установить глобальное значение по умолчанию, метод фильтра должен быть обернут декоратором @staticmethod, чтобы предотвратить ввод аргумента self.

TarFile.add(name, arcname=None, recursive=True, *, filter=None):

Метод TarFile.add() добавляет имя name в архив. Аргумент name может быть любым типом файла - каталог, fifo, символическая ссылка и т. д.

Если задан аргумент arcname, то он должен указывать альтернативное имя для файла в архиве. Каталоги добавляются рекурсивно по умолчанию. Этого можно избежать, установив recursive=False. Аргумент recursive добавляет записи в отсортированном порядке.

Если указан аргумент filter, то это должна быть функция, которая принимает аргумент объекта TarInfo и возвращает измененный объект TarInfo. Если вместо этого возвращается None, то объект TarInfo будет исключен из архива.

import tarfile

def reset(tarinfo):
    """Сбрасывает информацию о пользователе"""
    tarinfo.uid = tarinfo.gid = 0
    tarinfo.uname = tarinfo.gname = "root"
    return tarinfo

# архивируемый каталог
path = '/home/docs-python/script/sql-script/'
# корневой путь в архиве
path_tar = 'sql-script'
with tarfile.open('filter.tar.gz', 'w:gz') as tar:
    tar.add(path, path_tar, filter=reset)

# смотрим что получилось
with tarfile.open('filter.tar.gz') as tar:
    print(tar.list())

# ?rwxrwxr-x root/root          0 2020-05-18 14:33:18 sql-script/ 
# ?rw-rw-r-- root/root       2687 2019-09-14 08:07:18 sql-script/Script-5.sql 
# ?rw-rw-r-- root/root       1371 2019-09-14 08:06:38 sql-script/Script-1.sql 
# ?rw-rw-r-- root/root         50 2019-09-14 08:00:46 sql-script/Script-3.sql 
# ?rw-rw-r-- root/root       3394 2019-09-14 08:07:34 sql-script/procedure.sql 
# ?rw-rw-r-- root/root       1130 2019-09-14 08:06:30 sql-script/Script-2.sql 
# ?rw-rw-r-- root/root       1163 2019-09-14 08:06:31 sql-script/Script-4.sql

TarFile.addfile(tarinfo, fileobj=None):

Метод TarFile.addfile() добавляет объект tarinfo в архив.

Если указан аргумент fileobj, это должен быть двоичный файл и из него считываются байты tarinfo.size и добавляются в архив. Можно создавать объекты TarInfo напрямую или с помощью TarFile.gettarinfo().

import tarfile

# архивируемый файл
file = 'test.py'

with tarfile.open('test.tar.gz', 'w:gz') as tar:
    info = tarfile.TarInfo(file)
    with open(file) as fp:
        tar.addfile(info, fp)

# смотрим что получилось
with tarfile.open('test.tar.gz') as tar:
    print(tar.list())

# ?rw-r--r-- 0/0          0 1970-01-01 03:00:00 test.py 
# None

TarFile.gettarinfo(name=None, arcname=None, fileobj=None):

Метод TarFile.gettarinfo() создает объект объект TarInfo из результата os.stat() или его эквивалента в существующем файле. Файл должен быть указан с имени name, либо указан как объект файла fileobj с дескриптором файла.

Аргумент name может быть объектом, похожим на путь. Если задан аргумент arcname, то он указывает альтернативное имя для файла в архиве, в противном случае имя берется из атрибута name файлового объекта fileobj или аргумента name. Имя должно быть текстовой строкой.

Можно изменить некоторые атрибуты TarInfo, прежде чем добавлять их с помощью метода TarFile.addfile(). Если файловый объект не является обычным файловым объектом, расположенным в начале файла, то атрибуты, такие как размер, могут нуждаться в изменении. Это касается таких объектов, как GzipFile. Имя также может быть изменено и в этом случае arcname может быть фиктивной строкой.

import tarfile

# архивируемый файл
file = 'test.py'

with tarfile.open('test.tar.gz', 'w:gz') as tar:
    info = tar.gettarinfo(file)
    tar.addfile(info)

# смотрим что получилось
with tarfile.open('test.tar.gz') as tar:
    print(tar.list())

# ?rw-rw-r-- docs-python/docs-python       3484 2020-05-19 14:49:46 test.py 
# None

TarFile.close():

Метод TarFile.close() закрывает открытый объект TarFile. В режиме записи добавляются в архив два завершающих нулевых блока.

import tarfile

tar = tarfile.open("sample.tar.gz")
tar.extractall()
tar.close()

# Эквивалентно

with tarfile.open("sample.tar.gz") as tar:
    tar.extractall()

TarFile.pax_headers:

Атрибут TarFile.pax_headers представляет собой словарь, содержащий пары ключ-значение глобальных заголовков pax.

import tarfile

with tarfile.open('sample.tar.bz2', 'r') as tar:
    print(tar.pax_headers)

# {}