找出csv.reader 在做什么的最可靠方法是阅读源代码。参见_csv.c,第 773 行以后。您会看到 reader 对象有一个指向底层迭代器(通常是文件迭代器)的指针,并且每次需要另一行时它都会调用 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 明确表示(参见 cmets),他关心的是 csv.reader 是否保持这些行处于活动状态,从而防止它们被 Python 的内存管理器收集。
同样,您可以阅读代码(最可靠)或尝试进行实验。如果您查看_csv.c 中Reader_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 不会挂在它从它的迭代器获取的对象上,如果没有其他东西让它们保持活动状态,那么它们会被及时地进行垃圾收集。
我感觉你没有告诉我们这个问题的更多内容。你能解释一下你为什么担心这个吗?