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.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.AbsolutePathError¶
Поднят для отказа в извлечении элемента с абсолютным путем.
- exception tarfile.OutsideDestinationError¶
Вызывается для отказа в извлечении элемента за пределы каталога назначения.
- exception tarfile.SpecialFileError¶
Вызывается для отказа в извлечении специального файла (например, устройства или канала).
- exception tarfile.AbsoluteLinkError¶
Поднят вопрос об отказе в извлечении символической ссылки с абсолютным путем.
- exception tarfile.LinkOutsideDestinationError¶
Поднят для отказа в извлечении символической ссылки, указывающей за пределы целевого каталога.
На уровне модуля доступны следующие константы:
- tarfile.ENCODING¶
Кодировка символов по умолчанию:
'utf-8'
в Windows, значение, возвращаемое с помощьюsys.getfilesystemencoding()
в противном случае.
Каждая из следующих констант определяет формат архива 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 указывает альтернативное имя файла в архиве, в противном случае имя берется из атрибута fileobjname
или аргумента name. Имя должно быть текстовой строкой.Вы можете изменить некоторые атрибуты
TarInfo
, прежде чем добавлять его с помощьюaddfile()
. Если файловый объект не является обычным файловым объектом, расположенным в начале файла, такие атрибуты, какsize
, могут потребовать изменения. Это относится к таким объектам, какGzipFile
.name
также может быть изменено, и в этом случае arcname может быть фиктивной строкой.Изменено в версии 3.6: Параметр name принимает значение path-like object.
Объекты 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
.
- 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.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.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
также предоставляет несколько удобных методов запроса:
Экстракционные фильтры¶
Добавлено в версии 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
.Для обычных файлов, включая жесткие ссылки:
Для других файлов (каталогов) установите для
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
Параметры командной строки¶
- -c <tarfile> <source1> ... <sourceN>¶
- --create <tarfile> <source1> ... <sourceN>¶
Создайте tar-файл из исходных файлов.
- -e <tarfile> [<output_dir>]¶
- --extract <tarfile> [<output_dir>]¶
Извлеките tar-файл в текущий каталог, если output_dir не указан.
-
-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 или когда сохраняются строки с заменяющими символами.