使用Python透明地挂载tar.gz归档文件

3
如何使用Python透明地挂载tar.gz存档文件?

我有一个tar.gz存档文件,其中的内容需要被外部程序读取。这些内容仅在临时情况下需要。我可以将其解压缩到临时文件夹中,并指定我的外部程序从那里读取它。之后,我可以删除临时文件夹。然而,这些存档文件可能很大(解压后大于1 GB),因此解压缩会占用大量磁盘空间。我的服务器在硬盘性能方面比较弱,我不能随意浪费空间,但是它拥有大量的RAM和CPU功率。

这就是为什么我想尝试在不完全解压缩的情况下透明地挂载存档文件。我发现了archivemount,它似乎正是我想要的。 是否有一种纯Python的方法来执行archivemount所做的事情?请不要使用subprocess.call“解决方案”。它应该在64位Linux上运行。

我相信应该有一种聪明的方式来使用tarfile来访问存档文件的内容,然后使用fusepy创建一个用户空间文件系统,以公开存档文件的内容。是否有人已经将这些部分组合在一起?有什么想法吗?

如果您认为这不是一个好主意,请发表相关评论。如果您知道更好的方法,请评论。


我认为使用archivemount是最简单的方法。它在各种发行版中都可以轻松获取,而且你只需要一个命令就可以挂载你的存档文件。fusepy已经两年没有更新了。根据你的具体需求,仅使用tarfile也可能足够。 - njzk2
1
您提到在暴露内容后使用 tarfile。这是一个嵌套的 tar 文件吗? - Dan Getz
@DanGetz 很好的建议,我编辑了问题以使其更清晰。我想首先使用 tarfile 访问存档文件,然后使用 fusepy 创建文件系统。 - Johannes P
你确定使用TarFile.extractfile()将文件读入内存不足以满足你的需求吗? - Dan Getz
@DanGetz 是的,非常确定。这些内容必须由外部程序阅读,该程序期望档案文件的内容就像它们在文件系统上被提取一样(包括文件夹层次结构)。我无法控制读取模块,因此不能简单地添加支持以读取档案文件。而且我不知道它将打开哪些文件,所以我需要提供所有东西。 - Johannes P
在现代Linux中,/tmp通常存储在内存中(通常为RAM的一半)。第二种可能性是/dev/shm。您应该了解“tmpfs”。 - Stefan
1个回答

2
截至版本0.3.1,我的 ratarmount 模块可以用于在 Python 中挂载 .tar.gz 文件,您可以使用它或查看其源代码。gzip 寻址支持来自依赖项 indexed_gzip。Ratarmount 本身基于 tarindexer,它实现了使用 tarfile 获取偏移量,然后进行寻址的想法。但是,ratarmount 添加了 FUSE 层以及其他可用性和性能功能。您可以从 PyPI 安装 ratarmount。
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接