Python中的Tarfile:我可以通过仅提取一些数据来更有效地解压吗?

Joe*_*Joe 7 python performance tarfile

我正在订购美国地质勘探局的大堆土地场景,这些场景来自tar.gz档案.我正在编写一个简单的python脚本来解压缩它们.每个存档包含15个60-120 mb大小的tiff图像,总计超过2 gb.我可以使用以下代码轻松提取整个存档:

import tarfile
fileName = "LT50250232011160-SC20140922132408.tar.gz"
tfile = tarfile.open(fileName, 'r:gz')
tfile.extractall("newfolder/")
Run Code Online (Sandbox Code Playgroud)

我实际上只需要15个tiff中的6个,在标题中标识为"乐队".这些是一些较大的文件,因此它们共同占据了大约一半的数据.所以,我认为我可以通过修改代码来加快这个过程,如下所示:

fileName = "LT50250232011160-SC20140922132408.tar.gz"
tfile = tarfile.open(fileName, 'r:gz')
membersList = tfile.getmembers()
namesList = tfile.getnames()
bandsList = [x for x, y in zip(membersList, namesList) if "band" in y]
print("extracting...")
tfile.extractall("newfolder/",members=bandsList)
Run Code Online (Sandbox Code Playgroud)

但是,为两个脚本添加一个计时器显示第二个脚本没有显着的效率增益(在我的系统上,两个脚本在一个场景上运行大约一分钟).虽然提取速度稍微快一点,但似乎这个增益可以通过确定首先需要提取哪些文件所花费的时间来抵消.

问题是,这种权衡取决于我正在做的事情,还是仅仅是我的代码效率低下的结果?我是python的新手,今天才发现tarfile,所以如果后者是真的我也不会感到惊讶,但是我还没有找到任何有效提取存档的部分建议.

谢谢!

cro*_*nos 6

您可以通过将tar文件作为流打开来更有效地执行此操作.(https://docs.python.org/2/library/tarfile.html#tarfile.open)

mkdir tartest
cd tartest/
dd if=/dev/urandom of=file1 count=100 bs=1M
dd if=/dev/urandom of=file2 count=100 bs=1M
dd if=/dev/urandom of=file3 count=100 bs=1M
dd if=/dev/urandom of=file4 count=100 bs=1M
dd if=/dev/urandom of=file5 count=100 bs=1M
cd ..
tar czvf test.tgz tartest
Run Code Online (Sandbox Code Playgroud)

现在看起来像这样:

import tarfile
fileName = "test.tgz"
tfile = tarfile.open(fileName, 'r|gz')
for t in tfile:
    if "file3" in t.name: 
        f = tfile.extractfile(t)
        if f:
            print(len(f.read()))
Run Code Online (Sandbox Code Playgroud)

请注意|open命令中的内容.我们只阅读了file3.

$ time python test.py

104857600

real    0m1.201s
user    0m0.820s
sys     0m0.377s
Run Code Online (Sandbox Code Playgroud)

如果我改r|gz回到r:gz我得到的:

$ time python test.py 
104857600

real    0m7.033s
user    0m6.293s
sys     0m0.730s
Run Code Online (Sandbox Code Playgroud)

大约快5倍(因为我们有5个相同大小的文件).这是因为标准的开放方式允许向后寻求; 它只能通过提取在压缩的tarfile中这样做(我不知道确切的原因).如果您以流形式打开,则无法再随机查找,但如果您按顺序阅读,这在您的情况下可能会更快.但是,你不能getnames事先做到.但在这种情况下,这不是必要的.


Phi*_*lip 5

问题是tar文件没有中央文件列表,但按顺序存储文件,并在每个文件之前先有标头。tar然后通过gzip 将文件压缩以提供给您tar.gz。对于tar文件,如果您不想提取某个文件,则只需跳过header->size存档中的下一个字节,然后读取下一个标头。如果压缩了归档文件,那么您仍然将不得不跳过那么多字节,不仅不是在归档文件内,而是在解压缩的数据流内- 对于某些压缩格式,这是可行的,但对于另一些压缩格式,则需要您将两者之间的所有数据都解压缩。

gzip属于压缩方案的后一类。因此,尽管您通过不将不需要的文件写入磁盘节省了一些时间,但是您的代码仍然对它们进行了解压缩。您可以通过重写非gzip存档的_Stream类来解决该问题,但是对于您的gz文件,您无能为力。