tarfile — Чтение и запись архивных файлов tar

Исходный код: Lib/tarfile.py


Модуль tarfile позволяет считывать и записывать tar-архивы, в том числе с использованием сжатия gzip, bz2 и lzma. Используйте модуль zipfile для чтения или записи файлов .zip или функций более высокого уровня в shutil.

Несколько фактов и цифр:

  • читает и записывает gzip, bz2 и lzma сжатые архивы, если доступны соответствующие модули.

  • поддерживается чтение и запись в формате POSIX.1-1988 (ustar).

  • поддержка чтения и записи для формата GNU tar, включая расширения longname и longlink, поддержка только для чтения всех вариантов расширения sparse, включая восстановление разреженных файлов.

  • поддержка чтения и записи в формате POSIX.1-2001 (pax).

  • обрабатывает каталоги, обычные файлы, жесткие ссылки, символьные ссылки, fifo, символьные устройства и блочные устройства, а также может получать и восстанавливать информацию о файлах, такую как метка времени, права доступа и владелец.

Изменено в версии 3.3: Добавлена поддержка сжатия lzma.

tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)

Возвращает объект TarFile в качестве имени пути name. Подробную информацию об объектах TarFile и разрешенных аргументах ключевого слова смотрите в разделе Объекты TarFile.

режим должен быть строкой вида 'filemode[:compression]', по умолчанию используется значение 'r'. Вот полный список комбинаций режимов:

режим

действие

'r' or 'r:*'

Откройте для чтения с прозрачным сжатием (рекомендуется).

'r:'

Открыт исключительно для чтения без сжатия.

'r:gz'

Открыт для чтения со сжатием в формате gzip.

'r:bz2'

Открыт для чтения со сжатием в формате bzip2.

'r:xz'

Открыт для чтения со сжатием lzma.

'x' или 'x:'

Создайте исключительно tar-файл без сжатия. Создайте исключение FileExistsError, если оно уже существует.

'x:gz'

Создайте tar-файл со сжатием в формате gzip. Создайте исключение FileExistsError, если оно уже существует.

'x:bz2'

Создайте файл tar со сжатием в формате bzip2. Создайте исключение FileExistsError, если оно уже существует.

'x:xz'

Создайте файл tar со сжатием lzma. Создайте исключение FileExistsError, если оно уже существует.

'a' or 'a:'

Открыт для добавления без сжатия. Файл будет создан, если он не существует.

'w' or 'w:'

Открыт для записи в несжатом виде.

'w:gz'

Открыт для записи в сжатом формате gzip.

'w:bz2'

Открыт для записи в сжатом виде в формате bzip2.

'w:xz'

Открыт для записи в сжатом виде на lzma.

Обратите внимание, что 'a:gz', 'a:bz2' или 'a:xz' невозможно. Если mode не подходит для открытия определенного (сжатого) файла для чтения, активируется ReadError. Чтобы избежать этого, используйте mode 'r'. Если метод сжатия не поддерживается, отображается значение CompressionError.

Если указан fileobj, он используется в качестве альтернативы file object, открытому в двоичном режиме для name. Предполагается, что он должен находиться в позиции 0.

Для режимов 'w:gz', 'r:gz', 'w:bz2', 'r:bz2', 'x:gz', 'x:bz2', tarfile.open() принимает ключевое слово аргумент compresslevel (по умолчанию 9), чтобы указать уровень сжатия файла.

Для режимов 'w:xz' и 'x:xz', tarfile.open() принимает аргумент ключевого слова preset, чтобы указать уровень сжатия файла.

Для специальных целей существует второй формат для mode: 'filemode|[compression]'. tarfile.open() возвращает объект TarFile, который обрабатывает свои данные в виде потока блоков. Случайный поиск по файлу производиться не будет. Если указано, fileobj может быть любым объектом, который имеет метод read() или write() (в зависимости от mode), который работает с байтами. bufsize определяет размер блока и по умолчанию равен 20 * 512 байт. Используйте этот вариант в сочетании, например, с sys.stdin.buffer, сокетом file object или ленточным устройством. Однако такой объект TarFile ограничен тем, что он не допускает произвольного доступа, см. Примеры. Возможные на данный момент режимы:

Режим

Действие

'r|*'

Откройте поток блоков tar для чтения с прозрачным сжатием.

'r|'

Откройте поток несжатых блоков tar для чтения.

'r|gz'

Откройте сжатый в формате gzip поток для чтения.

'r|bz2'

Откройте сжатый поток в формате bzip2 для чтения.

'r|xz'

Откройте сжатый поток lzma для чтения.

'w|'

Откройте несжатый поток для записи.

'w|gz'

Откройте сжатый в формате gzip поток для записи.

'w|bz2'

Откройте сжатый поток в формате bzip2 для записи.

'w|xz'

Откройте сжатый поток lzma для записи.

Изменено в версии 3.5: Был добавлен режим 'x' (эксклюзивное создание).

Изменено в версии 3.6: Параметр name принимает значение path-like object.

class tarfile.TarFile

Класс для чтения и записи tar-архивов. Не используйте этот класс напрямую: используйте вместо него tarfile.open(). Смотрите Объекты TarFile.

tarfile.is_tarfile(name)

Возвращает True, если name является файлом архива tar, который может быть прочитан модулем tarfile. name может быть str, файлом или файлоподобным объектом.

Изменено в версии 3.9: Поддержка файлов и файлоподобных объектов.

Модуль tarfile определяет следующие исключения:

exception tarfile.TarError

Базовый класс для всех исключений tarfile.

exception tarfile.ReadError

Возникает при открытии tar-архива, который либо не может быть обработан модулем tarfile, либо каким-либо образом недействителен.

exception tarfile.CompressionError

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

exception tarfile.StreamError

Возникает из-за ограничений, которые характерны для потокоподобных объектов TarFile.

exception tarfile.ExtractError

Вызывается для нефатальных ошибок при использовании TarFile.extract(), но только если TarFile.errorlevel== 2.

exception tarfile.HeaderError

Вызывается с помощью TarInfo.frombuf(), если полученный буфер является недопустимым.

exception tarfile.FilterError

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

tarinfo

Информация об участнике, которую фильтр отказался извлекать, имеет вид TarInfo.

exception tarfile.AbsolutePathError

Поднят для отказа в извлечении элемента с абсолютным путем.

exception tarfile.OutsideDestinationError

Вызывается для отказа в извлечении элемента за пределы каталога назначения.

exception tarfile.SpecialFileError

Вызывается для отказа в извлечении специального файла (например, устройства или канала).

exception tarfile.AbsoluteLinkError

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

exception tarfile.LinkOutsideDestinationError

Поднят для отказа в извлечении символической ссылки, указывающей за пределы целевого каталога.

На уровне модуля доступны следующие константы:

tarfile.ENCODING

Кодировка символов по умолчанию: 'utf-8' в Windows, значение, возвращаемое с помощью sys.getfilesystemencoding() в противном случае.

tarfile.REGTYPE
tarfile.AREGTYPE

Обычный файл type.

tarfile.LNKTYPE

Ссылка (внутри файла tar) type.

tarfile.SYMTYPE

Символическая ссылка type.

tarfile.CHRTYPE

Специальное устройство для обозначения символа type.

tarfile.BLKTYPE

Специальное устройство для блокировки type.

tarfile.DIRTYPE

Каталог type.

tarfile.FIFOTYPE

Специальное устройство FIFO type.

tarfile.CONTTYPE

Непрерывный файл type.

tarfile.GNUTYPE_LONGNAME

Длинное имя GNU tar type.

Длинная ссылка на GNU tar type.

tarfile.GNUTYPE_SPARSE

Разреженный файл GNU tar type.

Каждая из следующих констант определяет формат архива tar, который может быть создан модулем tarfile. Подробности смотрите в разделе Поддерживаемые форматы tar.

tarfile.USTAR_FORMAT

Формат POSIX.1-1988 (ustar).

tarfile.GNU_FORMAT

Формат GNU tar.

tarfile.PAX_FORMAT

Формат POSIX.1-2001 (pax).

tarfile.DEFAULT_FORMAT

Формат по умолчанию для создания архивов. На данный момент это PAX_FORMAT.

Изменено в версии 3.8: Формат по умолчанию для новых архивов был изменен с GNU_FORMAT на PAX_FORMAT.

См.также

Модуль zipfile

Документация к стандартному модулю zipfile.

Операции архивирования

Документация о средствах архивирования более высокого уровня, предоставляемых стандартным модулем shutil.

GNU tar manual, Basic Tar Format

Документация к архивным файлам tar, включая расширения GNU tar.

Объекты TarFile

Объект TarFile предоставляет интерфейс к архиву tar. Архив tar представляет собой последовательность блоков. Элемент архива (сохраненный файл) состоит из блока заголовка, за которым следуют блоки данных. Один и тот же файл можно сохранять в архиве tar несколько раз. Каждый элемент архива представлен объектом TarInfo, подробности см. в разделе Объекты TarInfo.

Объект TarFile может использоваться в качестве контекстного менеджера в инструкции with. Он будет автоматически закрыт, когда блок будет завершен. Пожалуйста, обратите внимание, что в случае возникновения исключения архив, открытый для записи, не будет завершен; будет закрыт только файловый объект, используемый внутри системы. Пример использования приведен в разделе Примеры.

Добавлено в версии 3.2: Добавлена поддержка протокола управления контекстом.

class tarfile.TarFile(name=None, mode='r', fileobj=None, format=DEFAULT_FORMAT, tarinfo=TarInfo, dereference=False, ignore_zeros=False, encoding=ENCODING, errors='surrogateescape', pax_headers=None, debug=0, errorlevel=1)

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

name - это путь к архиву. name может быть path-like object. Его можно опустить, если указан fileobj. В этом случае используется атрибут файлового объекта name, если он существует.

режим - это либо 'r' для чтения из существующего архива, 'a' для добавления данных в существующий файл, 'w' для создания нового файла, перезаписывающего существующий, либо 'x' для создавайте новый файл только в том случае, если он еще не существует.

Если задано значение fileobj, оно используется для чтения или записи данных. Если это можно определить, то mode заменяется режимом fileobj. fileobj будет использоваться с позиции 0.

Примечание

fileobj не закрывается, когда TarFile закрыто.

формат определяет формат архива для записи. Это должна быть одна из констант USTAR_FORMAT, GNU_FORMAT или PAX_FORMAT, которые определяются на уровне модуля. При чтении формат будет определен автоматически, даже если в одном архиве присутствуют разные форматы.

Аргумент tarinfo можно использовать для замены класса TarInfo по умолчанию на другой.

Если значение разыменования равно False, добавьте в архив символьные и жесткие ссылки. Если значение True, добавьте содержимое целевых файлов в архив. Это не влияет на системы, которые не поддерживают символьные ссылки.

Если значение ignore_zeros равно False, обработайте пустой блок как конец архива. Если значение True, пропустите пустые (и недопустимые) блоки и постарайтесь получить как можно больше участников. Это полезно только для чтения связанных или поврежденных архивов.

debug может быть установлен в диапазоне от 0 (нет отладочных сообщений) до 3 (все отладочные сообщения). Сообщения записываются в sys.stderr.

уровень ошибок управляет обработкой ошибок извлечения, см. the corresponding attribute.

Аргументы encoding и errors определяют кодировку символов, которая будет использоваться для чтения или записи в архив, и способ обработки ошибок преобразования. Настройки по умолчанию будут работать для большинства пользователей. Более подробную информацию смотрите в разделе Проблемы с Юникодом.

Аргумент pax_headers представляет собой необязательный словарь строк, который будет добавлен в качестве глобального заголовка pax, если format равен PAX_FORMAT.

Изменено в версии 3.2: Используйте 'surrogateescape' в качестве значения по умолчанию для аргумента errors.

Изменено в версии 3.5: Был добавлен режим 'x' (эксклюзивное создание).

Изменено в версии 3.6: Параметр name принимает значение path-like object.

classmethod TarFile.open(...)

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

TarFile.getmember(name)

Возвращает объект TarInfo для элемента name. Если name не может быть найдено в архиве, вызывается KeyError.

Примечание

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

TarFile.getmembers()

Возвращает элементы архива в виде списка объектов TarInfo. Список имеет тот же порядок, что и элементы в архиве.

TarFile.getnames()

Возвращает участников в виде списка их имен. Он имеет тот же порядок, что и список, возвращаемый с помощью getmembers().

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

Напечатайте оглавление в виде sys.stdout. Если значение подробный равно False, будут напечатаны только имена участников. Если это True, то выводится результат, аналогичный результату ls -l. Если задан параметр «необязательные элементы», он должен быть подмножеством списка, возвращаемого getmembers().

Изменено в версии 3.5: Добавлен параметр members.

TarFile.next()

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

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

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

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

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

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

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

Установите filter='data', чтобы предотвратить наиболее опасные проблемы с безопасностью, и подробнее ознакомьтесь с разделом Экстракционные фильтры.

Изменено в версии 3.5: Добавлен параметр numeric_owner.

Изменено в версии 3.6: Параметр path принимает значение path-like object.

Изменено в версии 3.11.4: Добавлен параметр filter.

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

Извлеките элемент из архива в текущий рабочий каталог, используя его полное имя. Информация о файле извлекается максимально точно. элемент может быть именем файла или объектом TarInfo. Вы можете указать другой каталог, используя path. путь может быть path-like object. Атрибуты файла (владелец, mtime, режим) задаются, если только значение set_attrs не равно false.

Аргументы numeric_owner и filter те же, что и для extractall().

Примечание

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

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

Смотрите предупреждение для extractall().

Установите filter='data', чтобы предотвратить наиболее опасные проблемы с безопасностью, и подробнее ознакомьтесь с разделом Экстракционные фильтры.

Изменено в версии 3.2: Добавлен параметр set_attrs.

Изменено в версии 3.5: Добавлен параметр numeric_owner.

Изменено в версии 3.6: Параметр path принимает значение path-like object.

Изменено в версии 3.11.4: Добавлен параметр filter.

TarFile.extractfile(member)

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

Изменено в версии 3.3: Возвращает объект io.BufferedReader.

TarFile.errorlevel: int

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

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

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

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

TarFile.extraction_filter

Добавлено в версии 3.11.4.

Значение extraction filter, используемое по умолчанию для аргумента filter в extract() и extractall().

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

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

В Python 3.12+ при выходе из extraction_filter=None будет выдаваться DeprecationWarning.

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

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

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

Добавьте в архив имя файла. имя может быть любым типом файла (каталог, fifo, символьная ссылка и т.д.). Если задано, arcname указывает альтернативное имя файла в архиве. По умолчанию каталоги добавляются рекурсивно. Этого можно избежать, установив для параметра recursive значение False. Рекурсия добавляет записи в отсортированном порядке. Если задан параметр filter, то это должна быть функция, которая принимает аргумент TarInfo object и возвращает измененный объект TarInfo. Если вместо этого он возвращает None, то объект TarInfo будет исключен из архива. Пример приведен в Примеры.

Изменено в версии 3.2: Добавлен параметр filter.

Изменено в версии 3.7: Рекурсия добавляет записи в отсортированном порядке.

TarFile.addfile(tarinfo, fileobj=None)

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

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

Создайте объект TarInfo из результата os.stat() или аналогичного результата для существующего файла. Файл либо называется name, либо указывается как file object fileobj с файловым дескриптором. имя может быть path-like object. Если задано, arcname указывает альтернативное имя файла в архиве, в противном случае имя берется из атрибута fileobj name или аргумента name. Имя должно быть текстовой строкой.

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

Изменено в версии 3.6: Параметр name принимает значение path-like object.

TarFile.close()

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

TarFile.pax_headers: dict

Словарь, содержащий пары ключ-значение глобальных заголовков pax.

Объекты TarInfo

Объект TarInfo представляет собой один элемент в TarFile. Помимо хранения всех необходимых атрибутов файла (таких как тип файла, размер, время, права доступа, владелец и т.д.), он предоставляет несколько полезных методов для определения его типа. Он * не* содержит данных самого файла.

TarInfo объекты возвращаются методами TarFile getmember(), getmembers() и gettarinfo().

Изменение объектов, возвращаемых с помощью getmember() или getmembers(), повлияет на все последующие операции с архивом. В тех случаях, когда это нежелательно, вы можете использовать copy.copy() или вызвать метод replace(), чтобы создать измененную копию за один шаг.

Нескольким атрибутам может быть присвоено значение None, указывающее на то, что часть метаданных не используется или неизвестна. Различные методы TarInfo обрабатывают None по-разному:

  • Методы extract() или extractall() будут игнорировать соответствующие метаданные, оставляя их установленными по умолчанию.

  • addfile() произойдет сбой.

  • list() выведет строку-заполнитель.

Изменено в версии 3.11.4: Добавлен replace() и обработка None.

class tarfile.TarInfo(name='')

Создайте объект TarInfo.

classmethod TarInfo.frombuf(buf, encoding, errors)

Создайте и верните объект TarInfo из строкового буфера buf.

Вызывает HeaderError, если буфер недействителен.

classmethod TarInfo.fromtarfile(tarfile)

Считайте следующий элемент из TarFile объекта tarfile и возвращайте его как TarInfo объект.

TarInfo.tobuf(format=DEFAULT_FORMAT, encoding=ENCODING, errors='surrogateescape')

Создайте строковый буфер из объекта TarInfo. Информацию об аргументах смотрите в конструкторе класса TarFile.

Изменено в версии 3.2: Используйте 'surrogateescape' в качестве значения по умолчанию для аргумента errors.

Объект TarInfo имеет следующие атрибуты общедоступных данных:

TarInfo.name: str

Имя участника архива.

TarInfo.size: int

Размер в байтах.

TarInfo.mtime: int | float

Время последнего изменения в секундах с момента epoch, как в os.stat_result.st_mtime.

Изменено в версии 3.11.4: Может быть установлено значение None для extract() и extractall(), в результате чего при извлечении этот атрибут не применяется.

TarInfo.mode: int

Биты разрешений, как для os.chmod().

Изменено в версии 3.11.4: Может быть установлено значение None для extract() и extractall(), в результате чего при извлечении этот атрибут не применяется.

TarInfo.type

Тип файла. type обычно является одной из этих констант: REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, CHRTYPE, BLKTYPE, GNUTYPE_SPARSE. Чтобы более удобно определить тип объекта TarInfo, воспользуйтесь приведенными ниже методами is*().

TarInfo.linkname: str

Имя целевого файла, которое присутствует только в TarInfo объектах типа LNKTYPE и SYMTYPE.

Для символьных ссылок (SYMTYPE), имя ссылки относится к каталогу, содержащему ссылку. Для жестких ссылок (LNKTYPE), имя ссылки относится к корневому каталогу архива.

TarInfo.uid: int

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

Изменено в версии 3.11.4: Может быть установлено значение None для extract() и extractall(), в результате чего при извлечении этот атрибут не применяется.

TarInfo.gid: int

Идентификатор группы пользователя, который изначально сохранил этого участника.

Изменено в версии 3.11.4: Может быть установлено значение None для extract() и extractall(), в результате чего при извлечении этот атрибут не применяется.

TarInfo.uname: str

Имя пользователя.

Изменено в версии 3.11.4: Может быть установлено значение None для extract() и extractall(), в результате чего при извлечении этот атрибут не применяется.

TarInfo.gname: str

Название группы.

Изменено в версии 3.11.4: Может быть установлено значение None для extract() и extractall(), в результате чего при извлечении этот атрибут не применяется.

TarInfo.chksum: int

Контрольная сумма заголовка.

TarInfo.devmajor: int

Основной номер устройства.

TarInfo.devminor: int

Младший номер устройства.

TarInfo.offset: int

Заголовок tar начинается здесь.

TarInfo.offset_data: int

Данные файла начинаются здесь.

TarInfo.sparse

Скудная информация о членах.

TarInfo.pax_headers: dict

Словарь, содержащий пары ключ-значение связанного расширенного заголовка pax.

TarInfo.replace(name=..., mtime=..., mode=..., linkname=..., uid=..., gid=..., uname=..., gname=..., deep=True)

Добавлено в версии 3.11.4.

Возвращает новую копию объекта TarInfo с измененными атрибутами. Например, чтобы вернуть TarInfo с именем группы, равным 'staff', используйте:

new_tarinfo = old_tarinfo.replace(gname='staff')

По умолчанию выполняется глубокая копия. Если значение deep равно false, копия является поверхностной, т.е. pax_headers и любые пользовательские атрибуты используются совместно с исходным объектом TarInfo.

Объект TarInfo также предоставляет несколько удобных методов запроса:

TarInfo.isfile()

Возвращает True, если объект TarInfo является обычным файлом.

TarInfo.isreg()

То же, что isfile().

TarInfo.isdir()

Верните True, если это каталог.

TarInfo.issym()

Верните True, если это символическая ссылка.

TarInfo.islnk()

Верните True, если это жесткая ссылка.

TarInfo.ischr()

Верните True, если это символьное устройство.

TarInfo.isblk()

Верните True, если это блочное устройство.

TarInfo.isfifo()

Верните True, если это FIFO.

TarInfo.isdev()

Верните True, если это одно из символьных устройств, блочных устройств или FIFO.

Экстракционные фильтры

Добавлено в версии 3.11.4.

Формат tar предназначен для отображения всех деталей UNIX-подобной файловой системы, что делает его очень мощным. К сожалению, эти функции позволяют легко создавать файлы tar, которые при извлечении оказывают нежелательное - и, возможно, вредоносное - воздействие. Например, при извлечении файла tar произвольные файлы могут быть перезаписаны различными способами (например, с помощью абсолютных путей, компонентов пути .. или символических ссылок, которые влияют на более поздние элементы).

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

См.также

PEP 706

Содержит дополнительную мотивацию и обоснование дизайна.

Аргументом filter для TarFile.extract() или extractall() может быть:

  • строка 'fully_trusted': Соблюдайте все метаданные, указанные в архиве. Следует использовать, если пользователь полностью доверяет архиву или выполняет собственную сложную проверку.

  • строка 'tar' Учитывает большинство специфичных для tar функций (т.е. функций UNIX-подобных файловых систем), но блокирует функции, которые с большой вероятностью могут оказаться неожиданными или вредоносными. Подробнее см. tar_filter().

  • строка 'data': Игнорирует или блокирует большинство функций, характерных для UNIX-подобных файловых систем. Предназначена для извлечения кроссплатформенных архивов данных. Подробнее см. data_filter().

  • None (по умолчанию): Используйте TarFile.extraction_filter.

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

    В Python 3.12 значение по умолчанию будет равно DeprecationWarning.

    В Python 3.14 вместо этого по умолчанию будет использоваться фильтр 'data'. Можно переключиться и раньше; см. TarFile.extraction_filter.

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

    filter(member: TarInfo, path: str, /) -> TarInfo | None
    

    Вызываемый объект вызывается непосредственно перед извлечением каждого элемента, поэтому он может учитывать текущее состояние диска. Оно может:

    • возвращает TarInfo объект, который будет использоваться вместо метаданных в архиве, или

    • возвращает None, в этом случае элемент будет пропущен, или

    • вызовите исключение, чтобы прервать операцию или пропустить элемент, в зависимости от errorlevel. Обратите внимание, что при прерывании извлечения extractall() архив может быть извлечен частично. Попытка очистки не выполняется.

Именованные фильтры по умолчанию

Предопределенные именованные фильтры доступны в виде функций, поэтому их можно повторно использовать в пользовательских фильтрах:

tarfile.fully_trusted_filter(member, path)

Верните участника без изменений.

Это реализует фильтр 'fully_trusted'.

tarfile.tar_filter(member, path)

Реализует фильтр 'tar'.

  • Удалите из имен файлов начальные косые черты (/ и os.sep).

  • Refuse для извлечения файлов с абсолютными путями (в случае, если имя является абсолютным даже после удаления косых черт, например, C:/foo в Windows). Возникает вопрос о AbsolutePathError.

  • Refuse для извлечения файлов, абсолютный путь к которым (после перехода по символическим ссылкам) окажется за пределами места назначения. Возникает вопрос о OutsideDestinationError.

  • Очистите биты высокого режима (setuid, setgid, sticky) и сгруппируйте другие биты записи (S_IWGRP | S_IWOTH).

Возвращает измененный элемент TarInfo.

tarfile.data_filter(member, path)

Реализует фильтр 'data'. В дополнение к тому, что делает tar_filter:

  • Refuse для извлечения ссылок (жестких или программных), которые ссылаются на абсолютные пути, или на те, которые ссылаются за пределы пункта назначения.

    При этом возникает AbsoluteLinkError или LinkOutsideDestinationError.

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

  • Refuse для извлечения файлов устройств (включая каналы). При этом возникает SpecialFileError.

  • Для обычных файлов, включая жесткие ссылки:

    • Установите права владельца на чтение и запись (S_IRUSR | S_IWUSR).

    • Удалите права доступа к группе и другим исполняемым файлам (S_IXGRP | S_IXOTH) если у владельца их нет (S_IXUSR).

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

  • Установите для информации о пользователе и группе (uid, gid, uname, gname) значение None, чтобы методы извлечения не задавали его.

Возвращает измененный элемент TarInfo.

Ошибки фильтрации

Когда фильтр отказывается извлекать файл, он генерирует соответствующее исключение, подкласс FilterError. Это приведет к прерыванию извлечения, если TarFile.errorlevel равно 1 или больше. При errorlevel=0 ошибка будет зарегистрирована, и элемент будет пропущен, но извлечение будет продолжено.

Подсказки для дальнейшей проверки

Даже с filter='data' tarfile не подходит для извлечения ненадежных файлов без предварительной проверки. Помимо прочего, предопределенные фильтры не предотвращают атаки типа «отказ в обслуживании». Пользователям следует выполнить дополнительные проверки.

Вот неполный список того, что следует учитывать:

  • Извлеките файл в new temporary directory, чтобы предотвратить, например, использование уже существующих ссылок и упростить очистку после неудачного извлечения.

  • При работе с ненадежными данными используйте внешние (например, на уровне операционной системы) ограничения на использование диска, памяти и процессора.

  • Сверяйте имена файлов с разрешенным списком символов (чтобы отфильтровать управляющие символы, вызывающие путаницу, разделители внешних путей и т.д.).

  • Убедитесь, что имена файлов имеют ожидаемые расширения (не рекомендуется использовать файлы, которые запускаются, когда вы “нажимаете на них”, или файлы без расширений, такие как специальные названия устройств Windows).

  • Ограничьте количество извлекаемых файлов, общий размер извлекаемых данных, длину имени файла (включая длину символической ссылки) и размер отдельных файлов.

  • Проверьте, нет ли файлов, которые были бы скрыты в файловых системах без учета регистра.

Также обратите внимание, что:

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

  • tarfile не защищает от проблем с “живыми” данными, например, когда злоумышленник изменяет целевой (или исходный) каталог во время извлечения (или архивации).

Поддержка старых версий Python

Фильтры извлечения были добавлены в Python 3.12 и перенесены в более старые версии в качестве обновлений для системы безопасности. Чтобы проверить, доступна ли эта функция, используйте, например, hasattr(tarfile, 'data_filter') вместо проверки версии Python.

В следующих примерах показано, как поддерживать версии Python с этой функцией и без нее. Обратите внимание, что установка extraction_filter повлияет на все последующие операции.

  • Полностью надежный архив:

    my_tarfile.extraction_filter = (lambda member, path: member)
    my_tarfile.extractall()
    
  • Используйте фильтр 'data', если он доступен, но вернитесь к поведению Python 3.11 ('fully_trusted'), если эта функция недоступна:

    my_tarfile.extraction_filter = getattr(tarfile, 'data_filter',
                                           (lambda member, path: member))
    my_tarfile.extractall()
    
  • Используйте фильтр 'data'; сбой, если он недоступен:

    my_tarfile.extractall(filter=tarfile.data_filter)
    

    или:

    my_tarfile.extraction_filter = tarfile.data_filter
    my_tarfile.extractall()
    
  • Используйте фильтр 'data'; предупредите, если он недоступен:

    if hasattr(tarfile, 'data_filter'):
        my_tarfile.extractall(filter='data')
    else:
        # remove this when no longer needed
        warn_the_user('Extracting may be unsafe; consider updating Python')
        my_tarfile.extractall()
    

Пример фильтра извлечения с отслеживанием состояния

В то время как методы извлечения из tarfile используют простой вызываемый фильтр, пользовательские фильтры могут быть более сложными объектами с внутренним состоянием. Может быть полезно записать их как контекстные менеджеры, которые будут использоваться следующим образом:

with StatefulFilter() as filter_func:
    tar.extractall(path, filter=filter_func)

Такой фильтр может быть записан, например, в виде:

class StatefulFilter:
    def __init__(self):
        self.file_count = 0

    def __enter__(self):
        return self

    def __call__(self, member, path):
        self.file_count += 1
        return member

    def __exit__(self, *exc_info):
        print(f'{self.file_count} files extracted')

Интерфейс командной строки

Добавлено в версии 3.4.

Модуль tarfile предоставляет простой интерфейс командной строки для взаимодействия с архивами tar.

Если вы хотите создать новый tar-архив, укажите его имя после параметра -c, а затем укажите имена файлов, которые должны быть включены:

$ python -m tarfile -c monty.tar  spam.txt eggs.txt

Передача каталога также допустима:

$ python -m tarfile -c monty.tar life-of-brian_1979/

Если вы хотите извлечь архив tar в текущий каталог, используйте опцию -e:

$ python -m tarfile -e monty.tar

Вы также можете распаковать архив tar в другой каталог, указав его имя:

$ python -m tarfile -e monty.tar  other-dir/

Для получения списка файлов в архиве tar используйте параметр -l:

$ python -m tarfile -l monty.tar

Параметры командной строки

-l <tarfile>
--list <tarfile>

Перечислите файлы в файле tar.

-c <tarfile> <source1> ... <sourceN>
--create <tarfile> <source1> ... <sourceN>

Создайте tar-файл из исходных файлов.

-e <tarfile> [<output_dir>]
--extract <tarfile> [<output_dir>]

Извлеките tar-файл в текущий каталог, если output_dir не указан.

-t <tarfile>
--test <tarfile>

Проверьте, является ли tar-файл допустимым или нет.

-v, --verbose

Подробный вывод.

--filter <filtername>

Определяет фильтр для --extract. Подробности смотрите в Экстракционные фильтры. Принимаются только строковые имена (то есть, fully_trusted, tar, и data).

Добавлено в версии 3.11.4.

Примеры

Как извлечь весь архив tar целиком в текущий рабочий каталог:

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

Как извлечь подмножество архива tar с TarFile.extractall(), используя функцию генератора вместо списка:

import os
import tarfile

def py_files(members):
    for tarinfo in members:
        if os.path.splitext(tarinfo.name)[1] == ".py":
            yield tarinfo

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

Как создать несжатый tar-архив из списка имен файлов:

import tarfile
tar = tarfile.open("sample.tar", "w")
for name in ["foo", "bar", "quux"]:
    tar.add(name)
tar.close()

Тот же пример с использованием инструкции with:

import tarfile
with tarfile.open("sample.tar", "w") as tar:
    for name in ["foo", "bar", "quux"]:
        tar.add(name)

Как прочитать архив tar, сжатый в формате gzip, и отобразить некоторую информацию о членах:

import tarfile
tar = tarfile.open("sample.tar.gz", "r:gz")
for tarinfo in tar:
    print(tarinfo.name, "is", tarinfo.size, "bytes in size and is ", end="")
    if tarinfo.isreg():
        print("a regular file.")
    elif tarinfo.isdir():
        print("a directory.")
    else:
        print("something else.")
tar.close()

Как создать архив и сбросить информацию о пользователе, используя параметр filter в TarFile.add():

import tarfile
def reset(tarinfo):
    tarinfo.uid = tarinfo.gid = 0
    tarinfo.uname = tarinfo.gname = "root"
    return tarinfo
tar = tarfile.open("sample.tar.gz", "w:gz")
tar.add("foo", filter=reset)
tar.close()

Поддерживаемые форматы tar

Существует три формата tar, которые можно создать с помощью модуля tarfile:

  • Формат POSIX.1-1988 ustar (USTAR_FORMAT). Поддерживает имена файлов длиной не менее 256 символов и имена ссылок длиной до 100 символов. Максимальный размер файла составляет 8 гигабайт. Это старый и ограниченный, но широко поддерживаемый формат.

  • Формат GNU tar (GNU_FORMAT). Поддерживает длинные имена файлов и ссылки на них, файлы размером более 8 гигабайт и разреженные файлы. Это стандарт де-факто для систем GNULinux. tarfile полностью поддерживает расширения GNU tar для длинных имен, поддержка разреженных файлов доступна только для чтения.

  • Формат POSIX.1-2001 pax (PAX_FORMAT). Это самый гибкий формат, практически не имеющий ограничений. Он поддерживает длинные имена файлов и ссылок, большие файлы и сохраняет пути к ним в переносимом виде. Современные реализации tar, включая GNU tar, bsdtarlibarchive и star, полностью поддерживают расширенные возможности pax; некоторые старые или не поддерживаемые библиотеки могут этого не делать, но должны обрабатывать архивы pax так, как если бы они были в универсально поддерживаемом формате ustar. Это текущий формат по умолчанию для новых архивов.

    Он расширяет существующий формат ustar, добавляя дополнительные заголовки для информации, которую невозможно сохранить иным способом. Существует два варианта заголовков pax: расширенные заголовки влияют только на последующий заголовок файла, глобальные заголовки действительны для всего архива и влияют на все последующие файлы. Все данные в заголовке pax закодированы в UTF-8 по соображениям переносимости.

Есть еще несколько вариантов формата tar, которые можно прочитать, но не создать:

  • Старый формат V7. Это первый формат tar из седьмого выпуска Unix, в котором хранятся только обычные файлы и каталоги. Имена не должны быть длиннее 100 символов, информация о названии группы пользователей отсутствует. В некоторых архивах неправильно рассчитаны контрольные суммы заголовков в случае полей, содержащих символы, отличные от ASCII.

  • Расширенный формат SunOS tar. Этот формат является вариантом формата pax для POSIX.1-2001, но несовместим.

Проблемы с Юникодом

Формат tar изначально был задуман для создания резервных копий на ленточных накопителях с основным упором на сохранение информации о файловой системе. В настоящее время архивы tar широко используются для распространения файлов и обмена архивами по сетям. Одна из проблем исходного формата (который является основой всех других форматов) заключается в том, что в нем отсутствует концепция поддержки различных кодировок символов. Например, обычный архив tar, созданный в системе UTF-8, не может быть корректно прочитан в системе Latin-1, если он содержит символы, отличные от ASCII. Текстовые метаданные (такие как имена файлов, названия ссылок, названия групп пользователей) будут отображаться поврежденными. К сожалению, нет способа автоматически определить кодировку архива. Формат pax был разработан для решения этой проблемы. Он хранит метаданные, отличные от ASCII, используя универсальную кодировку символов UTF-8.

Детали преобразования символов в tarfile определяются ключевыми словами encoding и errors класса TarFile.

encoding определяет кодировку символов, используемую для метаданных в архиве. По умолчанию используется значение sys.getfilesystemencoding() или 'ascii' в качестве запасного варианта. В зависимости от того, считывается архив или записывается, метаданные должны быть либо декодированы, либо закодированы. Если кодировка задана неправильно, это преобразование может завершиться ошибкой.

Аргумент errors определяет, как обрабатываются символы, которые не могут быть преобразованы. Возможные значения перечислены в разделе Обработчики ошибок. По умолчанию используется схема 'surrogateescape', которую Python также использует для своих вызовов файловой системы, см. Имена файлов, аргументы командной строки и переменные среды.

Для архивов PAX_FORMAT (по умолчанию) кодировка обычно не требуется, поскольку все метаданные хранятся с использованием UTF-8. кодировка используется только в редких случаях, когда декодируются двоичные заголовки pax или когда сохраняются строки с заменяющими символами.

Вернуться на верх