如何提取.tar.gz成员中的文件?

3
我的目标是解压一个 .tar.gz 文件,不包括其子目录。
我的代码基于这个 问题,只不过我要解压的是一个 .tar.gz 文件,而不是一个 .zip 文件。
我提出这个问题是因为我得到的错误信息非常模糊,没有指明我的代码存在什么问题:
import os
import shutil
import tarfile

with tarfile.open('RTLog_20150425T152948.gz', 'r:gz') as tar:
    for member in tar.getmembers():
        filename = os.path.basename(member.name)
        if not filename:
            continue

        # copy file (taken from zipfile's extract)
        source = member
        target = open(os.path.join(os.getcwd(), filename), "wb")
        with source, target:
            shutil.copyfileobj(source, target)

你可以看到,我复制了链接问题中的代码,并尝试将其更改为处理.tar.gz成员而不是.zip成员。运行代码时,我会得到以下错误:

Traceback (most recent call last):
  File "C:\Users\dzhao\Desktop\123456\444444\blah.py", line 27, in <module>
    with source, target:
AttributeError: __exit__

根据我所阅读的资料,shutil.copyfileobj接受两个“类似文件”的对象作为输入。 member是一个TarInfo对象。我不确定TarInfo对象是否是一个类似文件的对象,因此我尝试将这一行更改为:

source = member #to
source = open(os.path.join(os.getcwd(), member.name), 'rb')

但是这导致了一个错误,文件找不到。

我哪里理解有误了吗?

1个回答

6
这段代码对我很有效:
import os
import shutil
import tarfile

with tarfile.open(fname, "r|*") as tar:
    counter = 0

    for member in tar:
        if member.isfile():
            filename = os.path.basename(member.name)
            if filename != "myfile": # do your check
                continue

            with open("output.file", "wb") as output: 
                shutil.copyfileobj(tar.fileobj, output, member.size)

            break # got our file

        counter += 1
        if counter % 1000 == 0:
            tar.members = [] # free ram... yes we have to do this manually

但是你的问题可能不是提取,而是你的文件确实不是 .tar.gz 文件,而只是一个 .gz 文件。
编辑:此外,你在第几行遇到错误是因为 Python 正试图调用成员对象的 __enter__ 函数(该函数不存在)。

我知道我的文件肯定是.tar.gz格式的。当我移除了"with source,target"这行代码后,我的初始担心被证实了。看起来我的源不是一个文件般的对象。在我查阅了什么是"tar.fileobj"之后,我将会尝试您的代码。 - Dzhao
修复方法是将源更改为tar.fileobj。有趣的是,当我在tar文档页面上使用ctrl+f时,它不是一个函数。因此,它必须是某个变量。但重要的是,tar.fileobj是类似文件的对象,所以现在我的代码可以工作了=)谢谢! - Dzhao
不客气。如果你正在处理大文件(100兆字节以上),我强烈建议包含免费的RAM行。虽然这在文档中没有提到,但如果你的脚本突然失败并且RAM使用率过高,它会让你感到惊讶。 - Simon Kirsten

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