我有一个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获取计数。
任何帮助都将不胜感激。
艾伦
答案 0 :(得分:28)
rows = list(myreader)
totalrows = len(rows)
for i, row in enumerate(rows):
print("Row %d/%d" % (i+1, totalrows))
答案 1 :(得分:15)
您只需要打开一次文件:
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()
的列表可能会浪费大量内存,而且不会更快。
注意:“Pythonic”方式是使用enumerate
而不是+=
,但UNPACK_TUPLE
操作码非常昂贵,使得enumerate
比增加本地速度慢。话虽这么说,你可能应该避免不必要的微观优化。
更多备注:如果您真的只想生成某种进度指示器,则不一定必须基于记录。您可以在循环中的文件对象上tell()
,只报告您通过的数据百分比。它会有点不平衡,但是任何大到足以保证记录长度偏差的文件都有可能在噪音中丢失。
答案 2 :(得分:2)
我找不到如何复制 迭代器。
最近的是itertools.tee,但正如@ J.F.Sebastian建议的那样,简单地制作一个list
就是最好的,正如itertools.tee的文档所解释的那样:
这个itertool可能需要很多 辅助存储(取决于如何 需要很多临时数据 存储)。一般来说,如果一个迭代器 之前使用大部分或全部数据 另一个迭代器启动,它更快 使用
list()
代替tee()
。
答案 3 :(得分:0)
如答案https://stackoverflow.com/a/2890569/8056572中所述,您可以通过将阅读器的长度转换为列表来获得行数。但是,这将对RAM消耗产生影响,并且您将失去读取器(它是一个生成器)的好处。
我认为最好的解决方案是将文件打开两次:
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))
注意:start=1
中的enumerate
表示i的第一个值。默认情况下为0,如果保留此默认值,则必须在打印语句中使用i + 1
如果您确实不想两次打开文件,则可以按照答案https://stackoverflow.com/a/2891061/8056572中所述使用seek
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))