Прозрачное монтирование архива tar.gz с помощью Python

Как я могу прозрачно смонтировать архив tar.gz с помощью Python?

У меня есть архив tar.gz, содержимое которого должно быть прочитано внешней программой. Содержимое понадобится только временно. Я мог бы просто распаковать его во временную папку и указать туда свою внешнюю программу для чтения. После этого я мог просто снова удалить временную папку. Однако архивы могут быть большими (>1 ГБ при извлечении), поэтому их распаковка займет много места на диске. Мой сервер довольно слаб с точки зрения производительности HD, и я не могу тратить свободное место впустую, но у него много оперативной памяти и мощности процессора.

Поэтому хочу попробовать смонтировать архив прозрачно, не распаковывая его целиком. Я наткнулся на archivemount Который, кажется, делает именно то, что я хочу. Есть ли способ сделать то же, что и archivemount в чистом Python? Не используйте subprocess.call "solutions", пожалуйста. Он должен работать на 64-битном Linux.

Я считаю, что должен быть умный способ использовать tarfile для доступа к содержимому архива, а затем fusepy для создания файловой системы пользовательского пространства, в которой отображается содержимое архива. Кто-нибудь уже собирал эти кусочки? Есть идеи?

Если вы считаете, что это не очень хорошая идея, пожалуйста, оставьте соответствующие комментарии. Если вы знаете, что лучше, пожалуйста, напишите.


person Johannes P    schedule 30.04.2014    source источник
comment
Я думаю, что использование archivemount - самый простой способ. он легко доступен в различных дистрибутивах, и вам нужна только 1 команда, чтобы смонтировать ваш архив. fupy не трогали 2 года. В зависимости от ваших конкретных потребностей, tarfile тоже может быть достаточно.   -  person njzk2    schedule 30.04.2014
comment
Вы упоминаете об использовании tarfile после раскрытия содержимого. Это tar внутри tar?   -  person Dan Getz    schedule 30.04.2014
comment
@DanGetz Хороший вопрос, я отредактировал вопрос, чтобы сделать его более понятным. Я хочу сначала использовать tarfile для доступа к архиву, а затем fusepy для создания файловой системы.   -  person Johannes P    schedule 30.04.2014
comment
Вы уверены, что чтения файлов в память с помощью TarFile.extractfile() недостаточно для того, что вы делаете?   -  person Dan Getz    schedule 30.04.2014
comment
@DanGetz Да, конечно. Содержимое должно быть прочитано внешней программой, которая ожидает, что содержимое архива будет извлечено из файловой системы (включая иерархию папок). Я не контролирую модуль чтения и, следовательно, не могу просто добавить поддержку чтения архивов. И я не знаю заранее, какие файлы он откроет, поэтому мне нужно дать ему все.   -  person Johannes P    schedule 01.05.2014
comment
В современных Linux /tmp часто хранится в памяти (часто в половине оперативной памяти). Второй вариант — /dev/shm. Вы должны прочитать о tmpfs.   -  person Stefan    schedule 01.05.2014


Ответы (1)


Начиная с версии 0.3.1 моего модуля ratarmount, вы можете использовать его или посмотреть его исходный код. для монтирования .tar.gz в Python. Поддержка поиска gzip зависит от зависимости indexed_gzip. Сам Ratarmount основан на tarindexer, который реализует идею использования tarfile для получения смещений и последующего поиска к нему. . Но ratarmount добавляет уровень FUSE среди других функций удобства использования и производительности.

Вы можете установить ratarmount из PyPI:

pip3 install --user ratarmount

а затем вызовите его интерфейс командной строки непосредственно из python следующим образом:

import ratarmount
ratarmount.cli( [ '--help' ] )
ratarmount.cli( [ pathToTar, pathToMountPoint ] )

Сердцем модуля является, как вы уже догадались, tarfile, который используется для перебрать все объекты TarInfo и создать список пути к файлу, смещения, размера, который затем можно использовать для прямого поиска смещения в необработанном файле tar и простого чтения байтов следующего размера. Это работает, потому что формат TAR настолько прост.

Вот неоптимизированная и очень голая основная идея:

import sys
import tarfile
from indexed_gzip import IndexedGzipFile

targzfile = sys.argv[1]
filetoprint = sys.argv[2]

index = {} # path : ( offset, size )

file = IndexedGzipFile( targzfile )
for tarinfo in tarfile.open( fileobj = file, mode = 'r|' ):
    index[tarinfo.name] = ( tarinfo.offset_data, tarinfo.size )

# at this point you could save or load the index for faster consecutive file seeks

file.seek( index[filetoprint][0] )
sys.stdout.buffer.write( file.read( index[filetoprint][1] ) )

Приведенный выше пример был протестирован для работы с:

wget -O- 'https://ftp.mozilla.org/pub/firefox/releases/70.0/linux-x86_64/en-US/firefox-70.0.tar.bz2' | bzip2 -d -c | gzip > firefox.tgz
python3 minimal-example.py firefox.tgz firefox/updater.ini
person mxmlnkn    schedule 23.11.2019