Автор оригинала: Doug Hellmann.
Цель:
Доступ к tar-архиву.
Модуль tarfile
обеспечивает доступ для чтения и записи к архивам tar Unix, включая сжатые файлы. Помимо стандартов POSIX, поддерживаются несколько расширений GNU tar. Также обрабатываются специальные типы файлов Unix, такие как жесткие и программные ссылки, а также узлы устройств.
Примечание
Хотя tarfile
реализует формат Unix, его также можно использовать для создания и чтения архивов tar в Microsoft Windows.
Тестирование файлов Tar
Функция is_tarfile ()
возвращает логическое значение, указывающее, относится ли имя файла, переданное в качестве аргумента, к допустимому архиву tar.
tarfile_is_tarfile.py
import tarfile for filename in ['README.txt', 'example.tar', 'bad_example.tar', 'notthere.tar']: try: print('{:>15} {}'.format(filename, tarfile.is_tarfile( filename))) except IOError as err: print('{:>15} {}'.format(filename, err))
Если файл не существует, is_tarfile ()
вызывает IOError
.
$ python3 tarfile_is_tarfile.py README.txt False example.tar True bad_example.tar False notthere.tar [Errno 2] No such file or directory: 'notthere.tar'
Чтение метаданных из архива
Используйте класс TarFile
для работы непосредственно с tar-архивом. Он поддерживает методы для чтения данных о существующих архивах, а также для изменения архивов путем добавления дополнительных файлов.
Чтобы прочитать имена файлов в существующем архиве, используйте getnames ()
.
tarfile_getnames.py
import tarfile with tarfile.open('example.tar', 'r') as t: print(t.getnames())
Возвращаемое значение – это список строк с именами содержимого архива.
$ python3 tarfile_getnames.py ['index.rst', 'README.txt']
Помимо имен, метаданные об элементах архива доступны как экземпляры объектов TarInfo
.
tarfile_getmembers.py
import tarfile import time with tarfile.open('example.tar', 'r') as t: for member_info in t.getmembers(): print(member_info.name) print(' Modified:', time.ctime(member_info.mtime)) print(' Mode :', oct(member_info.mode)) print(' Type :', member_info.type) print(' Size :', member_info.size, 'bytes') print()
Загрузите метаданные с помощью getmembers ()
и getmember ()
.
$ python3 tarfile_getmembers.py index.rst Modified: Fri Aug 19 16:27:54 2016 Mode : 0o644 Type : b'0' Size : 9878 bytes README.txt Modified: Fri Aug 19 16:27:54 2016 Mode : 0o644 Type : b'0' Size : 75 bytes
Если имя элемента архива известно заранее, его объект TarInfo
можно получить с помощью getmember ()
.
tarfile_getmember.py
import tarfile import time with tarfile.open('example.tar', 'r') as t: for filename in ['README.txt', 'notthere.txt']: try: info t.getmember(filename) except KeyError: print('ERROR: Did not find {} in tar archive'.format( filename)) else: print('{} is {:d} bytes'.format( info.name, info.size))
Если элемент архива отсутствует, getmember ()
вызывает KeyError
.
$ python3 tarfile_getmember.py README.txt is 75 bytes ERROR: Did not find notthere.txt in tar archive
Извлечение файлов из архива
Чтобы получить доступ к данным из элемента архива в программе, используйте метод extractfile ()
, передав имя элемента.
tarfile_extractfile.py
import tarfile with tarfile.open('example.tar', 'r') as t: for filename in ['README.txt', 'notthere.txt']: try: f t.extractfile(filename) except KeyError: print('ERROR: Did not find {} in tar archive'.format( filename)) else: print(filename, ':') print(f.read().decode('utf-8'))
Возвращаемое значение – это объект в виде файла, из которого может быть прочитано содержимое члена архива.
$ python3 tarfile_extractfile.py README.txt : The examples for the tarfile module use this file and example.tar as data. ERROR: Did not find notthere.txt in tar archive
Чтобы распаковать архив и записать файлы в файловую систему, используйте вместо него extract ()
или extractall ()
.
tarfile_extract.py
import tarfile import os os.mkdir('outdir') with tarfile.open('example.tar', 'r') as t: t.extract('README.txt', 'outdir') print(os.listdir('outdir'))
Член или члены считываются из архива и записываются в файловую систему, начиная с каталога, указанного в аргументах.
$ python3 tarfile_extract.py ['README.txt']
Документация стандартной библиотеки включает примечание о том, что extractall ()
безопаснее, чем extract ()
, особенно для работы с потоковыми данными, когда перемотка для чтения более ранней части ввода невозможно, и его следует использовать в большинстве случаев.
tarfile_extractall.py
import tarfile import os os.mkdir('outdir') with tarfile.open('example.tar', 'r') as t: t.extractall('outdir') print(os.listdir('outdir'))
В extractall ()
первым аргументом является имя каталога, в который должны быть записаны файлы.
$ python3 tarfile_extractall.py ['README.txt', 'index.rst']
Чтобы извлечь определенные файлы из архива, передайте их имена или контейнеры метаданных TarInfo
в extractall ()
.
tarfile_extractall_members.py
import tarfile import os os.mkdir('outdir') with tarfile.open('example.tar', 'r') as t: t.extractall('outdir', members[t.getmember('README.txt')], ) print(os.listdir('outdir'))
Если предоставляется список members
, извлекаются только названные файлы.
$ python3 tarfile_extractall_members.py ['README.txt']
Создание новых архивов
Чтобы создать новый архив, откройте TarFile
в режиме 'w'
.
tarfile_add.py
import tarfile print('creating archive') with tarfile.open('tarfile_add.tar', mode'w') as out: print('adding README.txt') out.add('README.txt') print() print('Contents:') with tarfile.open('tarfile_add.tar', mode'r') as t: for member_info in t.getmembers(): print(member_info.name)
Любой существующий файл обрезается и запускается новый архив. Чтобы добавить файлы, используйте метод add ()
.
$ python3 tarfile_add.py creating archive adding README.txt Contents: README.txt
Использование альтернативных имен членов архива
Можно добавить файл в архив, используя имя, отличное от исходного имени файла, создав объект TarInfo
с альтернативным arcname
и передав его в addfile ( )
.
tarfile_addfile.py
import tarfile print('creating archive') with tarfile.open('tarfile_addfile.tar', mode'w') as out: print('adding README.txt as RENAMED.txt') info out.gettarinfo('README.txt', arcname'RENAMED.txt') out.addfile(info) print() print('Contents:') with tarfile.open('tarfile_addfile.tar', mode'r') as t: for member_info in t.getmembers(): print(member_info.name)
В архиве только измененное имя файла:
$ python3 tarfile_addfile.py creating archive adding README.txt as RENAMED.txt Contents: RENAMED.txt
Запись данных из источников, отличных от файлов
Иногда возникает необходимость записать данные в архив прямо из памяти. Вместо того, чтобы записывать данные в файл, а затем добавлять этот файл в архив, вы можете использовать addfile ()
для добавления данных из открытого файлового дескриптора, который возвращает байты.
tarfile_addfile_string.py
import io import tarfile text 'This is the data to write to the archive.' data text.encode('utf-8') with tarfile.open('addfile_string.tar', mode'w') as out: info tarfile.TarInfo('made_up_file.txt') info.size len(data) out.addfile(info, io.BytesIO(data)) print('Contents:') with tarfile.open('addfile_string.tar', mode'r') as t: for member_info in t.getmembers(): print(member_info.name) f t.extractfile(member_info) print(f.read().decode('utf-8'))
Создав сначала объект TarInfo
, члену архива можно присвоить любое желаемое имя. После установки размера данные записываются в архив с использованием addfile ()
и буфера BytesIO
в качестве источника данных.
$ python3 tarfile_addfile_string.py Contents: made_up_file.txt This is the data to write to the archive.
Добавление в архив
Помимо создания новых архивов, можно добавить к существующему файлу, используя режим 'a'
.
tarfile_append.py
import tarfile print('creating archive') with tarfile.open('tarfile_append.tar', mode'w') as out: out.add('README.txt') print('contents:',) with tarfile.open('tarfile_append.tar', mode'r') as t: print([m.name for m in t.getmembers()]) print('adding index.rst') with tarfile.open('tarfile_append.tar', mode'a') as out: out.add('index.rst') print('contents:',) with tarfile.open('tarfile_append.tar', mode'r') as t: print([m.name for m in t.getmembers()])
Результирующий архив заканчивается двумя участниками:
$ python3 tarfile_append.py creating archive contents: ['README.txt'] adding index.rst contents: ['README.txt', 'index.rst']
Работа со сжатыми архивами
Помимо обычных файлов архива tar, модуль tarfile
может работать с архивами, сжатыми по протоколам gzip или bzip2. Чтобы открыть сжатый архив, измените строку режима, переданную в open ()
, чтобы включить ": gz"
или ": bz2"
, в зависимости от желаемый метод сжатия.
tarfile_compression.py
import tarfile import os fmt '{:<30} {:<10}' print(fmt.format('FILENAME', 'SIZE')) print(fmt.format('README.txt', os.stat('README.txt').st_size)) FILES [ ('tarfile_compression.tar', 'w'), ('tarfile_compression.tar.gz', 'w:gz'), ('tarfile_compression.tar.bz2', 'w:bz2'), ] for filename, write_mode in FILES: with tarfile.open(filename, modewrite_mode) as out: out.add('README.txt') print(fmt.format(filename, os.stat(filename).st_size), end' ') print([ m.name for m in tarfile.open(filename, 'r:*').getmembers() ])
При открытии существующего архива для чтения укажите "r: *"
, чтобы tarfile
определял метод сжатия для автоматического использования.
$ python3 tarfile_compression.py FILENAME SIZE README.txt 75 tarfile_compression.tar 10240 ['README.txt'] tarfile_compression.tar.gz 213 ['README.txt'] tarfile_compression.tar.bz2 199 ['README.txt']
Смотрите также
- стандартная библиотека документации для tarfile
- GNU tar manual – Документация по формату tar, включая расширения.
- zipfile – аналогичный доступ для ZIP-архивов.
- gzip – сжатие GNU zip
- bz2 – сжатие bzip2