关于python:如何仅提取.tar.gz成员的文件?

How do I extract only the file of a .tar.gz member?

我的目标是解压缩.tar.gz文件,而不是它的子目录,直到文件。

我的代码是基于这个问题,除了解压缩.zip我解压缩.tar.gz文件。

我问这个问题,因为我得到的错误非常模糊,并且没有在我的代码中发现问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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成员。 运行代码后,我收到以下错误:

1
2
3
4
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将两个"类似文件"的对象作为输入。 memberTarInfo对象。 我不确定TarInfo对象是否是类文件对象所以我尝试更改此行:

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

但这可以理解地引发了找不到文件的错误。

我不明白的是什么?


这段代码对我有用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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文件。

编辑:也是你在with行上得到错误,因为python试图调用成员对象的__enter__函数(不存在)。