2009-07-09 6 views
9

Je voudrais lire 20 lignes à partir d'un fichier csv:Python: exception StopIteration et liste compréhensions

rows = [csvreader.next() for i in range(20)] 

fonctionne très bien si le fichier a 20 ou plusieurs lignes, échoue avec une exception StopIteration autrement.

Existe-t-il une manière élégante de traiter un itérateur qui pourrait lancer une exception StopIteration dans une liste de compréhension ou devrais-je utiliser une boucle for normale?

Répondre

11

Vous pouvez utiliser itertools.islice. C'est la version d'itération du découpage de liste. Si l'itérateur a moins de 20 éléments, il retournera tous les éléments.

import itertools 
rows = list(itertools.islice(csvreader, 20)) 
+0

Merci Ayman. Il semble que la compréhension des listes doive être mise à jour pour faire face à StopIteration, non? Il semble que "for" a déjà été mis à jour pour y faire face (il arrête d'itérer quand il rencontre l'exception, l'attrape implicitement), et je ne vois pas de raison évidente pour que la compréhension des listes ne fasse pas la même chose. – Parand

+2

pour attraper le StopIteration par rapport à son itérable, pas à d'autres tels objets dans sa suite. Par exemple c = iter (plage (5)) pour i dans la plage (10): \t impression i, c.next() soulèvera l'exception StopIteration par rapport à c. – Mapio

+3

Une boucle for n'attrape PAS implicitement StopIteration. Elle ne l'attrape que si elle est lancée par la méthode suivante de l'itérateur, et non si elle est lancée dans le corps de la boucle. Dans votre question, csvreader.next() est analogue au corps de la boucle. – Miles

-1

Si pour une raison quelconque, vous devez également garder une trace du numéro de la ligne, je vous recommande:

rows = zip(xrange(20), csvreader) 

Sinon, vous pouvez dépouiller ou après ... eh bien, vous feriez mieux d'essayer autre option plus optimale depuis le début :-)

+0

Si vous avez besoin du numéro de ligne, vous devriez sûrement utiliser enumerate() .. –

0

itertools.izip (2) est un moyen de faire facilement la liste compréhensions fonctionnent, mais islice semble être la voie à suivre dans ce cas.

from itertools import izip 
[row for (row,i) in izip(csvreader, range(20))] 
+0

qui a l'avantage de ne pas s'appuyer sur len() (par exemple pour apsw.cursor) – Mark

+0

'enumerate' est la bonne façon de le faire , pas de zipper une gamme. – ArekBulski

Questions connexes