csv.DictReader中的行数
我有一个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 个回答
在之前的回答中提到,你可以通过把读取器转换成列表来获取行数。不过,这样做会占用更多的内存,而且你会失去读取器的好处,因为读取器其实是一个生成器。
我认为最好的解决办法是打开文件两次:
- 第一步,计算行数:
total_rows = sum(1 for _ in open('myFile.csv')) # -1 if you want to remove the header from the count
注意:我没有使用 .readlines()
,这样可以避免把所有行都加载到内存中。
- 第二步,逐行处理文件内容。
根据你的代码片段,你会得到类似这样的内容:
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))
你只需要打开文件一次:
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()
方法来获取当前读取到文件的哪个位置,然后报告你已经处理了多少百分比的数据。虽然这样可能会有些不均匀,但对于任何足够大的文件来说,记录长度的偏差在整体数据中几乎是微不足道的。
在编程中,有时候我们需要处理一些数据,这些数据可能来自不同的地方,比如用户输入、文件或者网络请求。为了让程序能够理解这些数据,我们通常需要将它们转换成一种特定的格式,这个过程就叫做“解析”。
解析的过程就像是把一堆杂乱无章的东西整理成有序的东西。比如说,如果你有一份购物清单,上面写着各种商品的名称和价格,你需要把这些信息提取出来,才能知道你要买什么和多少钱。
在编程中,解析通常涉及到将字符串(就是一串字符)转换成更有用的数据结构,比如数字、列表或者对象。这样,程序就能更方便地使用这些数据了。
总之,解析就是把复杂的东西变简单,让程序能够理解和使用数据。
rows = list(myreader)
totalrows = len(rows)
for i, row in enumerate(rows):
print("Row %d/%d" % (i+1, totalrows))