csv.DictReader中的行数

47 投票
4 回答
64150 浏览
提问于 2025-04-15 23:02

我有一个csv的DictReader对象(使用的是Python 3.1),但我想在开始遍历之前,先知道里面有多少行/列。就像下面这样……

myreader = csv.DictReader(open('myFile.csv', newline=''))

totalrows = ?

rowcount = 0
for row in myreader:
    rowcount +=1
    print("Row %d/%d" % (rowcount,totalrows))

我知道可以通过遍历这个读取器来获取总数,但那样的话我就不能再用'for'循环了。我可以遍历这个读取器的一个副本,但我找不到怎么复制一个迭代器。

我也可以使用

totalrows = len(open('myFile.csv').readlines())

但那样似乎是多此一举,因为要重新打开文件。如果可以的话,我更希望直接从DictReader中获取行数。

任何帮助都非常感谢。

Alan

4 个回答

3

在之前的回答中提到,你可以通过把读取器转换成列表来获取行数。不过,这样做会占用更多的内存,而且你会失去读取器的好处,因为读取器其实是一个生成器。

我认为最好的解决办法是打开文件两次:

  1. 第一步,计算行数:
total_rows = sum(1 for _ in open('myFile.csv')) # -1 if you want to remove the header from the count

注意:我没有使用 .readlines(),这样可以避免把所有行都加载到内存中。

  1. 第二步,逐行处理文件内容。

根据你的代码片段,你会得到类似这样的内容:

import csv

totalrows = sum(1 for _ in open('myFile.csv'))

myreader = csv.DictReader(open('myFile.csv'))

for i, _ in enumerate(myreader, start=1):
    print("Row %d/%d" % (i, totalrows))

注意:在 enumerate 中的 start=1 表示 i 的起始值。默认情况下是 0,如果你保持这个默认值,在打印的时候需要用 i + 1


如果你真的不想打开文件两次,可以使用 seek,具体可以参考这个回答 https://stackoverflow.com/a/2891061/8056572

import csv

f = open('myFile.csv')

total_rows = sum(1 for _ in f)

f.seek(0)

myreader = csv.DictReader(f)

for i, _ in enumerate(myreader, start=1):
    print("Row %d/%d" % (i, totalrows))
23

你只需要打开文件一次:

import csv

f = open('myFile.csv', 'rb')

countrdr = csv.DictReader(f)
totalrows = 0
for row in countrdr:
  totalrows += 1

f.seek(0)  # You may not have to do this, I didn't check to see if DictReader did

myreader = csv.DictReader(f)
for row in myreader:
  do_work

无论你做什么,你都需要进行两次遍历(当然,如果你的记录长度是固定的,那就另当别论了,你可以直接获取文件大小然后除以记录长度,但我们假设不是这种情况)。再次打开文件其实花费不大,但你可以像这里展示的那样避免这样做。为了使用 len() 而把文件内容转换成列表,可能会浪费很多内存,而且速度也不会更快。

注意:在Python中,推荐使用 enumerate 而不是 +=,但 UNPACK_TUPLE 这个操作的开销很大,所以使用 enumerate 反而比直接增加一个局部变量要慢。话虽如此,这可能是一个不必要的微优化,建议你还是避免这样做。

更多说明:如果你只是想生成某种进度指示器,它不一定要基于记录。你可以在循环中使用 tell() 方法来获取当前读取到文件的哪个位置,然后报告你已经处理了多少百分比的数据。虽然这样可能会有些不均匀,但对于任何足够大的文件来说,记录长度的偏差在整体数据中几乎是微不足道的。

56

在编程中,有时候我们需要处理一些数据,这些数据可能来自不同的地方,比如用户输入、文件或者网络请求。为了让程序能够理解这些数据,我们通常需要将它们转换成一种特定的格式,这个过程就叫做“解析”。

解析的过程就像是把一堆杂乱无章的东西整理成有序的东西。比如说,如果你有一份购物清单,上面写着各种商品的名称和价格,你需要把这些信息提取出来,才能知道你要买什么和多少钱。

在编程中,解析通常涉及到将字符串(就是一串字符)转换成更有用的数据结构,比如数字、列表或者对象。这样,程序就能更方便地使用这些数据了。

总之,解析就是把复杂的东西变简单,让程序能够理解和使用数据。

rows = list(myreader)
totalrows = len(rows)
for i, row in enumerate(rows):
    print("Row %d/%d" % (i+1, totalrows))

撰写回答