如何将我的 .tar.gz 文件转换为 shutil.copyfileobj 的类文件对象?

Posted

技术标签:

【中文标题】如何将我的 .tar.gz 文件转换为 shutil.copyfileobj 的类文件对象?【英文标题】:How do I to turn my .tar.gz file into a file-like object for shutil.copyfileobj? 【发布时间】:2016-06-10 20:51:02 【问题描述】:

我的目标是从.tar.gz 文件中提取一个文件,而不是提取所需文件之前的子目录。我正在尝试将我的方法从 question 中提取出来。我已经问过我自己的question,但我认为可行的答案似乎并没有完全奏效。

简而言之,shutil.copyfileobj 不会复制我的文件内容。

我的代码现在是:

import os
import shutil
import tarfile
import gzip

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

        source = tar.fileobj
        target = open('out', "wb")
        shutil.copyfileobj(source, target)

运行此代码后,文件out 已成功创建,但该文件为空。我知道我想提取的这个文件实际上有很多信息(大约 450 kb)。 print(member.size) 返回 1564197

我试图解决这个问题没有成功。 print(type(tar.fileobj)) 告诉我 tar.fileobj<gzip _io.BufferedReader name='RTLog_20150425T152948.gz' 0x3669710>

因此我尝试将source 更改为:source = gzip.open(tar.fileobj),但这引发了以下错误:

Traceback (most recent call last):
  File "C:\Users\dzhao\Desktop\123456\444444\blah.py", line 15, in <module>
    shutil.copyfileobj(source, target)
  File "C:\Python34\lib\shutil.py", line 67, in copyfileobj
    buf = fsrc.read(length)
  File "C:\Python34\lib\gzip.py", line 365, in read
    if not self._read(readsize):
  File "C:\Python34\lib\gzip.py", line 433, in _read
    if not self._read_gzip_header():
  File "C:\Python34\lib\gzip.py", line 297, in _read_gzip_header
    raise OSError('Not a gzipped file')
OSError: Not a gzipped file

为什么shutil.copyfileobj 没有实际复制.tar.gz 中文件的内容?

【问题讨论】:

您在shutil.copyfileobj() 中缺少大小选项。您应该包括member.size,否则它将读取到 tar 文件的末尾。我怀疑它会解决你的实际问题 @AlastairMcCormack 哦,我直到 tar 文件末尾才意识到它已经读过了。在这种情况下,这没什么大不了的,因为 tarfile 只是一个文件,但是谢谢! 【参考方案1】:

fileobj 不是 TarFile 的记录属性。它可能是用于表示整个 tar 文件的内部对象,而不是特定于当前文件的对象。

使用TarFile.extractfile() 获取特定成员的类文件对象:

…
source = tar.extractfile(member)
target = open("out", "wb")
shutil.copyfile(source, target)

【讨论】:

extractfile() 肯定会提取文件,但我得到文件前面的杂乱子目录。我只想复制文件而不是它附带的子目录。 嗯?尽管(具有误导性!)名称,tar.extractfile() 不会自行提取任何内容。它只是返回一个类似文件的对象。 好吧,对不起,我把 extractfile() 误认为是 extract()extractall()。我试过你的代码,它可以工作。虽然我认为我已经很好地阅读了 tarfile 文档,但我显然没有。谢谢!

以上是关于如何将我的 .tar.gz 文件转换为 shutil.copyfileobj 的类文件对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不解压的情况下将 gz 文件合并为 tar.gz?

把.zip文件转化为.tar.gz文件

如何在水壶中解压缩和导入 .tar.gz 文件?

如何将我的 .htaccess 文件转换为 NGINX?

如何将我的 Java 程序转换为 .exe 文件?

如何把文件压缩成tar.gz