gpt4 book ai didi

python - Tarfile 在第一个常规文件后停止

转载 作者:太空宇宙 更新时间:2023-11-04 10:49:24 30 4
gpt4 key购买 nike

我有 .tar.bz2 文件,里面有很多小的 json 文件。一个存档可能有大约数千个,而且 json 很小(低于 10kB,通常也低于 1 KB)。因此,压缩后的单个存档不会超过 100kB。

根据 the documentation , 下面的函数应该返回一个 tar 文件中所有常规文件的迭代器,返回它们的 tarinfo 结构和数据。

import tarfile

def tariter(filename):
with tarfile.open(filename) as archive:
while True:
tarinfo = archive.next()
if tarinfo is None:
break

if tarinfo.isreg():
handle = archive.extractfile(tarinfo.name)
data = handle.read()
handle.close()

yield tarinfo, data

然而,与其相反,它只是返回一个迭代器,该迭代器返回它的第一个文件(连同内容),然后停止。显然,archive.next() 在读取第二个成员后返回 None,即使存档中有很多文件。

这段代码中是否存在错误?

最佳答案

解决方法是直接使用带有 tarinfo 的 extractfile 而不是名称。这有效:

def tariter(filename):
with tarfile.open(filename) as archive:
while True:
tarinfo = archive.next()
if tarinfo is None:
break

if tarinfo.isreg():
handle = archive.extractfile(tarinfo) # LINE CHANGED
data = handle.read()
handle.close()

yield tarinfo, data

至于为什么会发生这种情况:TarFile.next() 没有实现迭代器协议(protocol),因为它返回None 而不是引发 StopIteration

迭代器协议(protocol)有两个部分:容器元素上返回迭代器的“外部”部分,以及迭代器本身的“内部”部分。

容器必须实现 __iter__(),它返回一个对象,它是迭代器。 TarFile.__iter__() 返回一个新的 TarIter 对象。

迭代器本身 (TarIter) 实现了 __iter__()(总是返回 self)和 next()。它还必须对原始容器中的项目有自己的独立索引。这使您可以在同一个容器上生成多个不同的迭代器,而不会让单独的迭代相互混淆。

但是,

TarFile.next() 为其迭代使用单独的索引,因此如果其他人使用 提供的伪迭代协议(protocol)TarFile 他们会搞乱迭代。

这似乎就是这里发生的事情。 TarFile.extractfile(filename) 使用 TarFile.next() 而不是 TarFile.__iter__ 在当前 TarFile 中查找匹配文件() 这是你使用的。这会破坏“下一项”索引,导致 archive.next() 在第一次 extractfile() 调用后返回 None

但是,如果您使用 extractfile(tarinfo)tarinfo 对象中有足够的元数据供 TarFile 提取字符串内容而无需通过 archive 对象查找匹配的文件名。因此,archive.extractfile(tarinfo) 可能比 archive.extractfile(tarinfo.name) 更快。​​

一般来说,集合对象(如 TarFile)应该迭代自己,而是生成一个新对象来迭代它们。 TarFile.next() 的存在本身就是糟糕的设计。也许有一个很好的理由,但不必使用它!

改为这样做:

def tariter(filename):
with tarfile.open(filename) as archive:
# use TarIter object for iteration over archive
for tarinfo in archive:
if tarinfo.isreg():
handle = archive.extractfile(tarinfo)
data = handle.read()
handle.close()
yield tarinfo, data

这更清晰,我敢打赌它也会更快一些。

关于python - Tarfile 在第一个常规文件后停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14913524/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com