Python 为什么行上的迭代会删除csv.reader和csv.reader中的数据?

Python 为什么行上的迭代会删除csv.reader和csv.reader中的数据?,python,csv,Python,Csv,创建任何非空的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 nonempt

创建任何非空的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)


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

csv.DictReader不会将整个数据读入内存,而是充当迭代器,根据需要使用
read\u file
中的行,而file对象
read\u 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
打开(“my.csv”)作为读取文件:
check_file=csv.DictReader(读取_文件)
#1) 对于非空csv文件,这将返回非空输出
对于check_文件中的行:
打印(行)

read_file.seek(0)#csv.DictReader
不会将整个数据读入内存,而是充当迭代器,根据需要使用
read_file
中的行,而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
打开(“my.csv”)作为读取文件:
check_file=csv.DictReader(读取_文件)
#1) 对于非空csv文件,这将返回非空输出
对于check_文件中的行:
打印(行)

read_file.seek(0)#在第一个文件中,它没有“删除数据”,因为数据从一开始就不在内存中;相反,它在底层文件对象上迭代到耗尽。在第二种情况下,您再次在开始处创建一个新的文件句柄。@alaniwi我明白了,所以reader/DictReader对象不会将csv加载到内存中,而是一次访问一行?是的,正是这样。它是基础文件对象的包装器,类似地一次访问一行文件。(实际上,它可能会在内存中使用固定大小的缓冲区来最小化从磁盘读取的请求,但您无法从Python访问这样的缓冲区。)在第一个缓冲区中,它没有“删除数据”,因为数据从一开始就不在内存中;相反,它在底层文件对象上迭代到耗尽。在第二种情况下,您再次在开始处创建一个新的文件句柄。@alaniwi我明白了,所以reader/DictReader对象不会将csv加载到内存中,而是一次访问一行?是的,正是这样。它是基础文件对象的包装器,类似地一次访问一行文件。(实际上,它可能会在内存中使用固定大小的缓冲区来最小化从磁盘读取的请求,但您无法从Python访问这样的缓冲区。)