J'ai un objet csv DictReader (en utilisant Python 3.1), mais je voudrais connaître le nombre de lignes/lignes contenues dans le lecteur avant je le parcourt. Quelque chose comme suit ...
myreader = csv.DictReader(open('myFile.csv', newline=''))
totalrows = ?
rowcount = 0
for row in myreader:
rowcount +=1
print("Row %d/%d" % (rowcount,totalrows))
Je sais que je pourrais obtenir le total en itérant à travers le lecteur, mais je ne pouvais pas exécuter la boucle "for". Je pourrais parcourir une copie du lecteur, mais je ne trouve pas comment copier un itérateur.
Je pourrais aussi utiliser
totalrows = len(open('myFile.csv').readlines())
mais cela semble une réouverture inutile du fichier. Je préfère obtenir le décompte du DictReader si possible.
Toute aide serait appréciée.
Alan
rows = list(myreader)
totalrows = len(rows)
for i, row in enumerate(rows):
print("Row %d/%d" % (i+1, totalrows))
Vous n'avez besoin d'ouvrir le fichier qu'une seule fois:
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
Peu importe ce que vous faites, vous devez effectuer deux passes (enfin, si vos enregistrements sont de longueur fixe - ce qui est peu probable - vous pouvez simplement obtenir la taille du fichier et la diviser, mais supposons que ce n'est pas le cas). Rouvrir le fichier ne vous coûte vraiment pas cher, mais vous pouvez l'éviter comme illustré ici. La conversion en une liste uniquement pour utiliser len()
va potentiellement gaspiller des tonnes de mémoire, et ne sera pas plus rapide.
Remarque: La méthode 'Pythonic' consiste à utiliser enumerate
au lieu de +=
, Mais l'opcode UNPACK_Tuple
Est si cher qu'il rend enumerate
plus lent que l'incrémentation d'un local. Cela étant dit, il s'agit probablement d'une micro-optimisation inutile que vous devriez probablement éviter.
Plus de notes: Si vous voulez vraiment simplement générer une sorte d'indicateur de progression, il ne doit pas nécessairement être basé sur des enregistrements. Vous pouvez tell()
sur l'objet fichier dans la boucle et simplement signaler le% des données que vous traversez. Ce sera un peu inégal, mais il y a des chances pour tout fichier suffisamment grand pour justifier une barre de progression que l'écart sur la longueur d'enregistrement sera perdu dans le bruit.
Je ne trouve pas comment copier un itérateur.
Le plus proche est itertools.tee , mais simplement en faire un list
, comme le suggère @ J.F.Sebastian, est mieux ici, comme l'expliquent les documents d'itertools.tee:
Cet outil peut nécessiter un stockage auxiliaire important (selon la quantité de données temporaires à stocker). En général, si un itérateur utilise la plupart ou la totalité des données avant le démarrage d'un autre itérateur, il est plus rapide d'utiliser
list()
au lieu detee()
.