csv 模块 => DictReader class Reader 对象:为什么我不能在文件关闭的情况下遍历 Reader 对象,但我可以访问它的属性?

csv module => DictReader class Reader Object: why can't I iterate through Reader Object with file closed, but I can access its attributes?

这可能是一个愚蠢的问题,但我对以下内容感到困惑:我从 csv 模块的 DictReader class 创建了一个 reader 对象。

以下代码 returns 一个错误,因为 csv 文件已经关闭,因为 for 循环没有缩进:

import csv
with open(file) as csvfile:
    reader = csv.DictReader(csvfile)
for row in reader:
    print(row)

returns 这个错误:

ValueError: I/O operation on closed file.

不过,我可以运行命令获取reader的属性,例如:

reader.fieldnames
reader.line_num

这是什么逻辑?我很困惑为什么我可以访问 reader 的属性,但不再遍历它。另外,我本以为一旦我分配:

reader = csv.DictReader(csvfile)

即使文件已关闭,我也应该能够访问 reader 的内容。

csv.DictReader(以及 csv.reader)以文件句柄对象作为参数构建。它不会复制句柄,或一次读取文件的全部内容,或诸如此类的事情。

当您退出 with 块时,此文件句柄将关闭,当 csv.DictReader 对象尝试访问它时,它会遇到 "closed file" 异常。请注意,with 块适用于原始文件句柄,而不适用于 csv.DictReader 对象。

csv.DictReader 对象仍然存在并且有效,但由于其源文件句柄已失效,因此不再可用于读取数据。

这与下面的简单示例没有什么不同:

class Foo:
    def __init__(self,source):
        self.source = source
    def bar(self):
        print(self.source)

lst = [1,2,3]
f = Foo(lst)
f.bar()  # prints [1, 2, 3]
lst.clear()
f.bar()  # prints []

以上,一旦 lst 被清除,f 对象将失去打印列表的能力,即使 f 对象本身仍然有效。

如果你想保留内容,你必须在一个单独的 list 对象中强制迭代文件,如果你想保留 reader 属性:

reader = csv.DictReader(csvfile)
contents = list(reader)