web-dev-qa-db-ja.com

csv.DictReaderの行数

Csv DictReaderオブジェクト(Python 3.1を使用)がありますが、リーダーに含まれる行/行の数を知りたいbefore繰り返し処理します。次のようなもの...

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からカウントを取得します。

任意の助けいただければ幸いです。

アラン

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

ファイルを開く必要があるのは一度だけです。

_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
_

何をするにしても、2つのパスを作成する必要があります(レコードが固定長である場合-これはありそうもありません-ファイルサイズを取得して分割するだけで済みますが、そうではないと仮定しましょう)。ファイルを再度開くことは実際にはそれほどコストはかかりませんが、ここに示されているようにそれを避けることができます。 len()を使用するためだけにリストに変換すると、大量のメモリが無駄になり、速度が低下する可能性があります。

注: 'Pythonic'の方法は、_+=_の代わりにenumerateを使用することですが、_UNPACK_Tuple_オペコードは非常に高価であるため、enumerateはローカルをインクリメントするよりも遅くなります。そうは言っても、おそらく避けるべき不必要なマイクロ最適化であろう。

その他の注意事項:ある種の進行状況インジケーターを生成したいだけの場合は、必ずしもレコードベースである必要はありません。ループ内のファイルオブジェクトに対してtell()を実行して、通過したデータの%をレポートすることができます。少し不均一になりますが、進行状況バーを保証するのに十分な大きさのファイルであれば、レコード長の偏差がノイズで失われる可能性があります。

15
Nick Bastin

イテレータをコピーする方法が見つかりません。

最も近いのは itertools.tee ですが、itertools.teeのドキュメントで説明されているように、@ J.F.Sebastianが示唆するように、単にlistを作成するのが最適です。

このitertoolは、かなりの補助ストレージを必要とする場合があります(保存する必要がある一時データの量によって異なります)。一般に、あるイテレーターが別のイテレーターが開始する前にほとんどまたはすべてのデータを使用する場合、list()の代わりにtee()を使用する方が高速です。

2
Alex Martelli