gpt4 book ai didi

python - 所有迭代器都缓存吗? csv.Reader 怎么样?

转载 作者:行者123 更新时间:2023-11-28 23:05:09 25 4
gpt4 key购买 nike

我们知道以下代码只是逐行加载数据,而不是将它们全部加载到内存中。即,已读行将以某种方式标记为操作系统“可删除”

def fileGen( file ):
for line in file:
yield line

with open("somefile") as file:
for line in fileGen( file ):
print line

但是如果我们将 fileGen 的定义修改为以下,我们是否可以验证这是否仍然正确?

def fileGen( file ):
for line in csv.Reader( file ):
yield line

我们怎么知道 csv.Reader 是否会缓存它加载的数据?谢谢

问候,约翰

最佳答案

找出csv.reader 正在做什么的最可靠方法是阅读源代码。参见 _csv.c ,第 773 行起。您会看到读取器对象有一个指向底层迭代器(通常是文件迭代器)的指针,并且每次需要另一行时它都会调用 PyIter_Next。因此它不会提前读取或以其他方式缓存它加载的数据。

找出csv.reader 正在做什么的另一种方法是创建一个模拟文件对象,该对象可以在查询时进行报告。例如:

class MockFile:
def __init__(self): self.line = 0
def __iter__(self): return self
def next(self):
self.line += 1
print "MockFile line", self.line
return "line,{0}".format(self.line)

>>> r = csv.reader(MockFile())
>>> next(r)
MockFile line 1
['line', '1']
>>> next(r)
MockFile line 2
['line', '2']

这证实了我们从阅读 csv 源代码中学到的东西:它仅在调用其自己的 next 方法时从底层迭代器请求下一行。


John 明确表示(参见评论)他担心的是 csv.reader 是否使行保持事件状态,防止它们被 Python 的内存管理器收集。

同样,您可以阅读代码(最可靠)或尝试实验。如果查看 _csv.cReader_iternext 的实现,您会发现 lineobj 是给返回对象的名称底层迭代器,并且在代码的每条路径上都有对 Py_DECREF(lineobj) 的调用。所以 csv.reader 不会让 lineobj 保持事件状态。

这里有一个实验来证实这一点。

class FinalizableString(string):
"""A string that reports its deletion."""
def __init__(self, s): self.s = s
def __str__(self): return self.s
def __del__(self): print "*** Deleting", self.s

class MockFile:
def __init__(self): self.line = 0
def __iter__(self): return self
def next(self):
self.line += 1
return FinalizableString("line,{0}".format(self.line))

>>> r = csv.reader(MockFile())
>>> next(r)
*** Deleting line,1
['line', '1']
>>> next(r)
*** Deleting line,2
['line', '2']

所以你可以看到 csv.reader 不会卡在它从迭代器中获取的对象上,如果没有其他东西让它们保持事件状态,那么它们会及时被垃圾收集.


我觉得这个问题还有更多内容您没有告诉我们。你能解释一下你为什么担心这个吗?

关于python - 所有迭代器都缓存吗? csv.Reader 怎么样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6546540/

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