csv.reader含字符串时seek(0)无法重置,求替代方法
嘿,作为新手碰到csv读取的这种小坑太正常啦!我来给你几个超实用的替代方案,帮你搞定重置csv_reader的需求~
方案1:提前把所有数据读到列表中(最推荐新手)
这是最简单省心的方法,一次性把CSV里的所有内容加载到一个列表里,之后你想怎么遍历、怎么重复调用都没问题,完全不用纠结文件指针、迭代器那些弯弯绕绕的特性。
修改后的代码示例:
import os import csv csv_path = os.path.join("..", "Resources", "budget_data_1.csv") with open(csv_path, newline="") as csvfile: # 直接把csv_reader转成列表,所有数据都存在all_data里 all_data = list(csv.reader(csvfile)) # 第一次遍历数据 print("第一次遍历数据:") for row in all_data: print(row) # 想"重置"的话,直接再遍历all_data就行,完全不会有问题 print("\n第二次遍历(相当于重置后):") for row in all_data: print(row)
为啥这个方法好用?因为数据存在内存里,重复访问速度快,而且操作逻辑直白——你不用管文件有没有读到末尾,只要调用这个列表就能重新获取所有数据。只要你的CSV文件不是特别大(比如几百MB那种),这个方法完全够用。
方案2:需要重置时重新打开文件
如果你的CSV文件特别大,不想占用太多内存,那可以在需要重新读取的时候,再次打开文件生成新的csv_reader对象。
代码示例:
import os import csv csv_path = os.path.join("..", "Resources", "budget_data_1.csv") # 第一次读取文件 with open(csv_path, newline="") as csvfile: csv_reader = csv.reader(csvfile) print("第一次遍历数据:") for row in csv_reader: print(row) # 需要"重置"的时候,重新打开文件创建新的reader print("\n第二次遍历(重新打开文件):") with open(csv_path, newline="") as csvfile: csv_reader = csv.reader(csvfile) for row in csv_reader: print(row)
这个方法的好处是不会把所有数据都存在内存里,适合处理大文件。缺点是每次重新打开文件会有一点点IO开销,但对于普通场景来说完全可以忽略。
为啥之前的seek(0)没用?
其实不是数据包含字符串的问题,而是csv.reader的本质是迭代器——一旦你把它遍历完,迭代器就处于"耗尽"状态了,哪怕你用csvfile.seek(0)把文件指针移回开头,这个已经耗尽的迭代器也没法再生成数据了。而且有时候文件打开的模式、newline参数的处理也会影响指针位置,导致seek操作达不到预期效果。
另外你提到"将列转为列表后还出现额外错误",大概率是因为你在迭代完csv_reader之后才转列表——这时候reader已经耗尽了,转出来的是空列表,自然会报错。用上面的方案1,先把所有数据转成列表,再从中提取列就没问题了,比如提取第二列(索引从0开始):
# 跳过表头,提取第二列数据 column_data = [row[1] for row in all_data[1:]]
内容的提问来源于stack exchange,提问作者Sara M.

