Python中用csv.DictReader统计CSV行数为何导致代码失效?
问题分析与解决办法
嘿,这个坑我之前踩过!核心问题在于文件对象是单向迭代器——一旦你把它从头到尾遍历一遍,文件指针就会停在文件末尾,后续再尝试读取就拿不到任何内容了。
具体原因
当你取消注释row_count = sum(1 for row in csvfile)时,sum(1 for row in csvfile)会遍历整个csvfile文件对象,把每一行都数一遍。这个过程结束后,文件指针已经移到了文件的最后位置。这时候再用csv.DictReader(csvfile)去初始化读取器,它从当前指针位置(也就是文件末尾)开始读,自然没有任何数据可以处理,所以循环for row in reader根本不会执行,控制台也就没有输出那些Processing内容。
同样,numberofrows = len(list(reader))的操作也会把reader这个迭代器完全遍历一遍(因为list()会把迭代器的所有元素取出来),后续再遍历reader时,它已经没有剩余元素了,结果一样。
两种解决办法
办法1:把文件指针移回开头
在遍历完文件计数后,调用csvfile.seek(0)把指针重置到文件起始位置,这样csv.DictReader就能重新读取整个文件了。这种方法适合大文件,不会占用太多内存:
import csv import os with open('test.csv') as csvfile: row_count = sum(1 for row in csvfile) csvfile.seek(0) # 关键:将文件指针移回文件开头 reader = csv.DictReader(csvfile, delimiter=';') path = os.getcwd() for row in reader: header = row['FirstName'] + ' ' + row['Surname'] + ' – #' + row['RecruitmentID'].zfill(5) print('Processing: ' + ' / ' + header)
办法2:先把所有行读入内存
如果文件不大,可以先把DictReader的所有行转换成列表存在内存里,这样既可以获取行数,又能反复遍历:
import csv import os with open('test.csv') as csvfile: reader = csv.DictReader(csvfile, delimiter=';') rows = list(reader) # 把所有行读入列表 row_count = len(rows) path = os.getcwd() for row in rows: header = row['FirstName'] + ' ' + row['Surname'] + ' – #' + row['RecruitmentID'].zfill(5) print('Processing: ' + ' / ' + header)
小提示
- 如果你的CSV文件有特殊编码或者带BOM头,
seek(0)可能需要额外处理,但大部分普通CSV文件都能直接用。 - 大文件优先用办法1,避免内存占用过高;小文件用办法2更简洁。
内容的提问来源于stack exchange,提问作者MrVocabulary
相关产品推荐
相关产品推荐

