支持python迭代的多文件归档格式



我最近意识到.tar.gz.zip存档文件都不支持对它们在python中包含的文件进行快速迭代。我来详细说明一下。

我收集了大量的文件。统计数据如下:

  • 文件数:4'810'289
  • 目录数:402'212
  • tar.gz归档文件为9GB
  • .zip归档文件大小为16GB
  • 未压缩数据重190GB

使用.tar.gz方法,我认为可以通过pickle下面代码的结果来创建索引:

with tarfile.open(self.file.path, "r:gz") as tar:
return tar.getmembers()

结果是一个大约2GB的pickle文件,但问题是您必须读取整个存档,以获取您想要提取的每个成员。实际上,之后运行tar.extractfile(member)对每个成员来说都需要几分钟!所以这里没有。

使用.zip方法略有不同,但仍然不能实现对文件的快速迭代。只要你执行:

from zipfile import ZipFile
zip = ZipFile(file_path)

模块似乎加载一个完整的文件到RAM中,因为解释器挂起大约5分钟,最终使用19GB的RAM(看top),只要你保持zip对象。之后zip.infolist()zip.open(member).read()非常快。所以至少比.tar.gz好。

在python中是否有一个多文件压缩归档格式,能够一个接一个地迭代文件,而无需加载完整文件,构建冗长的索引或每次读取整个文件?

谢谢。

我没有看到ZipFile行为。这是一个16gb的zip文件,大约有11,000个条目。内存使用量远不及zip文件的大小:

Python 3.9.6 (default, Sep 26 2022, 11:37:49) 
[Clang 14.0.0 (clang-1400.0.29.202)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tracemalloc
>>> tracemalloc.start()
>>> print(tracemalloc.get_traced_memory())
(8797, 11854)
>>> from zipfile import ZipFile
>>> print(tracemalloc.get_traced_memory())
(1429688, 1448932)
>>> zip = ZipFile("/Users/madler/Downloads/iCloud Photos Part 12 of 12.zip")
>>> print(tracemalloc.get_traced_memory())
(9208481, 10508727)
>>> info = zip.infolist()
>>> len(info)
11341
>>> print(tracemalloc.get_traced_memory())
(9210488, 10508727)

据我所知,所有的命令都立即执行。

我希望内存使用与zip文件中的条目数成正比,而不是与zip文件大小成正比。ZipFile应该只是将zip文件的中心目录读入内存。在我的例子中,我看到每个条目大约有700字节的内存。据推测,如果文件名的长度相当,那么您的文件大约需要3 GB。这是一个不错的内存块,但肯定不是19gb。

相关内容

  • 没有找到相关文章

最新更新