读取 Python 中的 .tar.gz 文件

Read .tar.gz file in Python

我有一个 25GB 的文本文件。所以我把它压缩到 tar.gz,它变成了 450 MB。现在我想从 python 读取该文件并处理我引用的文本 data.for 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'

此外,还有其他方法可以完成此任务吗?

docs 告诉我们 Noneextractfile() 返回不是常规文件或 link.

一种可能的解决方案是跳过 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()
如果成员既不是文件也不是 link,

tarfile.extractfile() 可以 return 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)

你可以试试这个

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

您不能 "read" 一些特殊文件的内容,例如链接 tar 支持它们,并且 tarfile 可以很好地提取它们。当 tarfile 提取它们时,它不是 return 类文件对象而是 None。你得到一个错误,因为你的 tarball 包含这样一个特殊的文件。

一种方法是在提取之前确定您正在处理的 tar 球中的条目类型:根据手头的这些信息,您可以决定是否可以 "read"文件。您可以通过调用 tarfile.getmembers() returns tarfile.TarInfos 来实现这一点,其中包含有关 tar 球中包含的文件类型的详细信息。

tarfile.TarInfo class 具有确定 tar 成员类型所需的所有属性和方法,例如 isfile()isdir()tinfo.islnk()tinfo.issym() 然后相应地决定对每个成员做什么(提取或不提取等)。

例如,我使用这些来测试 this patched tarfile 中的文件类型,以跳过提取特殊文件并以特殊方式处理链接:

for tinfo in tar.getmembers():
    is_special = not (tinfo.isfile() or tinfo.isdir()
                      or tinfo.islnk() or tinfo.issym())
...

在 Jupyter notebook 中你可以像下面那样做

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

我的需求:

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

问题:

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

解法:

  1. 首先检查 tar 对象的类型。我参考了 tar 文件库的 doc 中的示例。 (搜索"How to read a gzip compressed tar archive and display some member information")
  2. 从字节 str 解码为普通 str。 (ref - 投票最多的答案)

代码:

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}.")