Python使用csv.DictReader读取CSV文件的三个常见疑问
尝试用csv.DictReader将CSV文件内容读取到变量中,先后测试了两种实现方案:
# option 1 dna = [] with open(sys.argv[1], "r") as file: dna = csv.DictReder(file) # 注:此处存在笔误,正确类名为csv.DictReader print(dna) # 输出结果: <csv.DictReader object at 0x123...> # option 2 dna = [] with open(sys.argv[1], "r") as file: reader = csv.DictReader(file) for row in reader: dna.append(row) print(dna) # 输出结果: 解析后的CSV行内容组成的数组
对应三点技术疑问:
- 为什么第一种方案执行
print(dna)时输出的是csv.DictReader对象的内存地址,而非实际的CSV文件内容? - 为什么第二种方案中需要定义
reader变量并逐行遍历,才能将CSV内容正确存入dna列表? - 部分同类实现代码中
open函数没有传入"r"模式参数,运行效果却完全一致,这是什么原因?
关于疑问1
csv.DictReader根本不是用来存数据的容器,它是个惰性迭代器。你把它直接赋值给dna的时候,程序只做了最基础的初始化:给这个读取器绑定了要读的文件句柄、存了CSV解析的规则,半行实际内容都没读。
Python里普通自定义类的实例,直接打印的时候默认输出格式就是「类名+内存地址」,它不会自动触发迭代器去读文件内容,所以你看到的就是一串对象标识,不可能直接出来CSV内容。
额外提一句:你贴的option1代码里类名拼错了,正确写法是csv.DictReader,少个a写成DictReder运行会直接报NameError,能拿到对象地址的输出说明你实际运行的时候是拼对的,只是贴代码手滑。
关于疑问2
还是惰性迭代器的设计逻辑:这种设计是为了处理超大体积的CSV文件——如果文件有几个G大,一次性把所有内容读进内存很容易把程序搞崩,惰性迭代器只会在你明确要拿某一行数据的时候,才去读对应位置的文件内容、解析成字典格式返回。
你写的for循环遍历的过程,就是主动告诉迭代器“我要拿所有行数据”,它才会逐行读、逐行解析,你每拿到一行就append到dna列表里,最后列表里存的才是真正解析完成的所有CSV内容。
嫌手动写循环麻烦的话,直接写dna = list(csv.DictReader(file))就能实现和option2完全一样的效果,list()接收迭代器当参数的时候,内部自动就会做逐行遍历、收集元素的操作,不用自己写循环。
关于疑问3
因为Python内置open()函数的默认打开模式就是只读文本模式'r',你不显式传"r"的时候,底层自动就按只读模式开文件,和你手动写了参数的逻辑没有任何区别,所以运行效果完全一致。
不过实际写代码还是建议显式把模式参数写上,一是别人看你代码一眼就知道你是要读还是要写,可读性好;二是避免极端场景下默认参数变动带来的兼容问题。
内容的提问来源于stack exchange,提问作者beginner

