首页 > 解决方案 > 为什么迭代行会删除 csv.reader 和 csv.DictReader 中的数据?

问题描述

创建任何非空 csv 文件并调用此 test.csv。考虑代码

import csv 

with open("test.csv") as read_file:
     #this test case also applies to csv.reader()
     check_file = csv.DictReader(read_file)
     
     #1) with a nonempty csv file, this will return a nonempty output
     for row in check_file:
         print(row)

     #2) this will not return any output
     for row in check_file:
         print(row)

换句话说,发生的事情是对行的迭代check_file删除了 中的所有数据check_file,因此 1) 返回非空输出但完全相同的函数 2) 根本不返回任何输出。

有一个简单但不优雅的解决方案:

import csv 

with open("test.csv") as read_file:
     #this test case also applies to csv.reader()
     check_file = csv.DictReader(read_file)
     
     #1) with a nonempty csv file, this will return a nonempty output
     for row in check_file:
         print(row)

with open("test.csv") as read_file:
     check_file = csv.DictReader(read_file)

     #2) this will return the same output as 1)
     for row in check_file:
         print(row)

这种奇怪行为的解释是什么?

标签: pythoncsv

解决方案


不会将csv.DictReader整个数据读入内存,而是充当迭代器,read_file按需使用行,而文件对象read_file反过来将按需从文件中读取行。当第一个循环完成时,文件指针位于文件末尾,第二次迭代将不再获得任何行。但是,如果您将文件指针倒回到第一行的末尾(与实例化后的位置相同csv.DictReader并且它已在标题行中读取),那么您可以使用现有对象再次迭代,而无需重新打开文件并创建一个新DictReader对象。

import csv 

with open("my.csv") as read_file:
    check_file = csv.DictReader(read_file)
     
    #1) with a nonempty csv file, this will return a nonempty output
    for row in check_file:
        print(row)

    read_file.seek(0)  # <==== back to the start
    next(read_file)  # <==== discard the header row
         
    #2) this will now give you output again...
    for row in check_file:
        print(row)

类似的考虑也适用于csv.reader(),尽管在这种情况下,如果您想再次重复相同的输出,您只需回到开头,而无需跳过标题行。


推荐阅读