我有一个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'
另外,还有其他方法可以完成这项任务吗?
答案 0 :(得分:21)
如果成员不是常规文件或链接,docs告诉我们 extractfile()返回无。
一种可能的解决方案是跳过无结果:
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()
答案 1 :(得分:4)
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)
答案 2 :(得分:1)
你可以试试这个
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
答案 3 :(得分:1)
你不能&#34;阅读&#34;一些特殊文件的内容,如链接,但tar支持它们,tarfile将提取它们。当tarfile
提取它们时,它不会返回类似文件的对象,而是返回None。并且您收到错误,因为您的tarball包含这样一个特殊文件。
一种方法是在提取之前确定您正在处理的tarball中的条目类型:有了这些信息,您可以决定是否可以阅读&#34;文件。您可以通过调用tarfile.getmembers()
返回tarfile.TarInfo
来实现此目的,其中包含有关tarball中包含的文件类型的详细信息。
tarfile.TarInfo
类具有确定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())
...
答案 4 :(得分:1)
我的需求:
utf-8
文本文件和目录组成。问题:
None
。extractfile(fname)
返回的内容是一个字节的str(例如b'Hello \ t \ xe4 \ xbd \ xa0 \ xe5 \ xa5 \ xbd')。 Unicode字符无法正确显示。 解决方案:
代码:
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}.")
答案 5 :(得分:0)
在Jupyter笔记本中,您可以执行以下操作
!wget -c http://qwone.com/~jason/20Newsgroups/20news-bydate.tar.gz -O - | tar -xz