在Python中读取.tar.gz文件

问题描述 投票:0回答:7

我有一个 25GB 的文本文件。所以我将其压缩为 tar.gz,它变成了 450 MB。现在我想从 python 读取该文件并处理文本数据。为此我提到了question。但就我而言,代码不起作用。代码如下:

import tarfile
import numpy as np 

tar = tarfile.open("filename.tar.gz", "r:gz")
for member in tar.getmembers():
     f=tar.extractfile(member)
     content = f.read()
     Data = np.loadtxt(content)

错误如下:

Traceback (most recent call last):
  File "dataExtPlot.py", line 21, in <module>
    content = f.read()
AttributeError: 'NoneType' object has no attribute 'read'

还有其他方法可以完成这项任务吗?

python file tar gzip
7个回答
48
投票

docs 告诉我们,如果成员不是常规文件或链接,则 extractfile() 返回 None

一种可能的解决方案是跳过“无”结果: tar = tarfile.open("filename.tar.gz", "r:gz") for member in tar.getmembers(): f = tar.extractfile(member) if f is not None: content = f.read()


如果成员既不是文件也不是链接,则

6
投票

tarfile.extractfile()

可以返回
None。例如,您的 tar 存档可能包含目录或设备文件。修复:

import tarfile import numpy as np tar = tarfile.open("filename.tar.gz", "r:gz") for member in tar.getmembers(): f = tar.extractfile(member) if f: content = f.read() Data = np.loadtxt(content)



3
投票

t = tarfile.open("filename.gz", "r") for filename in t.getnames(): try: f = t.extractfile(filename) Data = f.read() print filename, ':', Data except : print 'ERROR: Did not find %s in tar archive' % filename



2
投票
我的需求:

Python3.
  1. 我的 tar.gz 文件由多个
  2. utf-8
  3. 文本文件和目录组成。
    需要从所有文件中读取文本行。
问题:

tar.getmembers() 返回的 tar 对象可能是
    None
  1. extractfile(fname)
  2. 返回的内容是一个字节str(例如b'Hello \xe4\xbd\xa0\xe5\xa5\xbd')。 Unicode 字符无法正确显示。
    
    
    
解决方案:

首先检查 tar 对象的类型。我参考了 tarfile lib 的
    doc
  1. 中的示例。 (搜索“如何读取gzip压缩的tar存档并显示一些成员信息”) 从字节str解码为普通str。 (
  2. ref
  3. - 得票最多的答案)
代码:

with tarfile.open("sample.tar.gz", "r:gz") as tar: for tarinfo in tar: logger.info(f"{tarinfo.name} is {tarinfo.size} bytes in size and is: ") if tarinfo.isreg(): logger.info(f"Is regular file: {tarinfo.name}") f = tar.extractfile(tarinfo.name) # To get the str instead of bytes str # Decode with proper coding, e.g. utf-8 content = f.read().decode('utf-8', errors='ignore') # Split the long str into lines # Specify your line-sep: e.g. \n lines = content.split('\n') for i, line in enumerate(lines): print(f"[{i}]: {line}\n") elif tarinfo.isdir(): logger.info(f"Is dir: {tarinfo.name}") else: logger.info(f"Is something else: {tarinfo.name}.")



1
投票
tarfile

提取它们时,它不会返回类似文件的对象,而是返回 None。你会得到一个错误,因为你的 tarball 包含这样一个特殊的文件。


一种方法是在提取 tarball 之前确定您正在处理的 tarball 中的条目类型:有了这些信息,您可以决定是否可以“读取”该文件。您可以通过调用

tarfile.getmembers()

返回

tarfile.TarInfo
来实现此目的,其中包含有关 tarball 中包含的文件类型的详细信息。

tarfile.TarInfo

类具有确定 tar 成员类型所需的所有属性和方法,例如

isfile()
isdir()
tinfo.islnk()
tinfo.issym()
,然后相应地决定对每个成员执行什么操作(摘录或不,等等)。

例如,我使用这些来测试

此修补的 tarfile

中的文件类型,以跳过提取特殊文件并以特殊方式处理链接: for tinfo in tar.getmembers(): is_special = not (tinfo.isfile() or tinfo.isdir() or tinfo.islnk() or tinfo.issym()) ...



0
投票

tar = tarfile.open(tar_archive, 'r:gz') files = tar.getmembers() seqs_file = tar.extractfile(files[0]) seqs_file = gzip.open(seqs_file, 'rt') content = seqs_file.readlines()

我认为如果你有更多文件,你可以循环并使用 gzip.open 将它们一一打开,但我没有测试。我希望这个解决方案对其他人有用。


-1
投票

!wget -c http://qwone.com/~jason/20Newsgroups/20news-bydate.tar.gz -O - | tar -xz

© www.soinside.com 2019 - 2024. All rights reserved.