不理解Python的csv.reader obj

2024-09-26 17:50:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我在python的内置csv模块中遇到了一个以前从未注意到的行为。通常,当我在csv中读取时,它会完全按照doc's进行,使用“with”打开文件,然后使用“for”循环遍历reader对象。但是,我最近尝试连续两次遍历csv.reader对象,结果发现第二个“for”循环什么也没有做。

import csv

with open('smallfriends.csv','rU') as csvfile:
readit = csv.reader(csvfile,delimiter=',')

for line in readit:
    print line

for line in readit:
    print 'foo'

控制台输出:

Austins-iMac:Desktop austin$ python -i amy.py 
['Amy', 'James', 'Nathan', 'Sara', 'Kayley', 'Alexis']
['James', 'Nathan', 'Tristan', 'Miles', 'Amy', 'Dave']
['Nathan', 'Amy', 'James', 'Tristan', 'Will', 'Zoey']
['Kayley', 'Amy', 'Alexis', 'Mikey', 'Sara', 'Baxter']
>>>
>>> readit
<_csv.reader object at 0x1023fa3d0>
>>> 

所以第二个“for”循环基本上什么也不做。我的一个想法是csv.reader对象在被读取一次后从内存中释放。但事实并非如此,因为它仍然保留它的内存地址。我发现一个post提到了类似的问题。他们给出的原因是,一旦对象被读取,指针就停留在内存地址的末尾,准备向对象写入数据。是这样吗?有人能更详细地说明这是怎么回事吗?有没有办法把指针推回到内存地址的开头来重读它?我知道这样做是不好的编码实践,但我主要是好奇,想了解更多关于Python框架下发生的事情。

谢谢!


Tags: csvcsvfile对象inforwithlinereader
3条回答

我将试着回答你关于读者在做什么以及为什么reset()seek(0)可能有帮助的其他问题。在最基本的形式中,csv阅读器可能如下所示:

def csv_reader(it):
    for line in it:
        yield line.strip().split(',')

也就是说,它接受生成字符串的任何迭代器并为您提供一个生成器。它所做的只是从迭代器中获取一个项,对其进行处理并返回该项。当消费it时,csv_读取器将退出。读者不知道迭代器是从哪里来的,也不知道如何正确地创建一个新的迭代器,所以它甚至不尝试重置自己。那是留给程序员的。

我们可以在读者不知道的情况下修改迭代器,也可以创建一个新的读者。这里有一些例子来证明我的观点。

data = open('data.csv', 'r')
reader = csv.reader(data)

print(next(reader))               # Parse the first line
[next(data) for _ in range(5)]    # Skip the next 5 lines on the underlying iterator
print(next(reader))               # This will be the 7'th line in data
print(reader.line_num)            # reader thinks this is the 2nd line
data.seek(0)                      # Go back to the beginning of the file
print(next(reader))               # gives first line again

data = ['1,2,3', '4,5,6', '7,8,9']
reader = csv.reader(data)         # works fine on lists of strings too
print(next(reader))               # ['1', '2', '3']

一般来说,如果您需要第二次访问,最好关闭/重新打开您的文件并使用新的csv阅读器。它的清洁和确保良好的簿记。

在csvreader上迭代只需包装对底层文件对象中的行的迭代。 在每次迭代中,读取器从文件中获取下一行,转换并返回它。

因此,对csvreader的迭代遵循与iterating over files相同的约定。 也就是说,一旦文件到达它的结尾,您就必须在第二次迭代之前寻找开始。

下面应该可以,虽然我还没有测试过:

import csv

with open('smallfriends.csv','rU') as csvfile:
    readit = csv.reader(csvfile,delimiter=',')

    for line in readit:
        print line

    # go back to the start of the file
    csvfile.seek(0)

    for line in readit:
        print 'foo

如果不是太多数据,您可以将其读入列表:

import csv

with open('smallfriends.csv','rU') as csvfile:
    readit = csv.reader(csvfile,delimiter=',')
    csvdata = list(readit)

    for line in csvdata :
        print line

    for line in csvdata :
        print 'foo'

相关问题 更多 >

    热门问题