2009-07-09 7 views
9

mi piacerebbe leggere al massimo 20 righe da un file CSV:Python: eccezione StopIteration e list comprehension

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

funziona bene se il file ha 20 o più righe, non riesce con un'eccezione StopIteration altrimenti.

Esiste un modo elegante per gestire un iteratore che potrebbe generare un'eccezione StopIteration in una lista di comprensione o dovrei utilizzare un ciclo regolare?

risposta

11

È possibile utilizzare itertools.islice. È la versione iteratore di slicing di elenchi. Se l'iteratore ha meno di 20 elementi, restituirà tutti gli elementi.

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

Grazie Ayman. Sembra che le intese sulle liste debbano essere aggiornate per gestire StopIteration, no? Sembra che "for" sia già stato aggiornato per affrontarlo (smette di iterare quando incontra l'eccezione, rilevandolo implicitamente), e non vedo un motivo ovvio per cui le list comprehensions non facciano lo stesso. – Parand

+2

per catturare StopIteration relativo al suo iterabile, non ad altri oggetti simili nella sua suite. Per esempio c = iter (intervallo (5)) for i in range (10): \t print i, c.next() solleverà l'eccezione StopIteration rispetto a c. – Mapio

+3

Un ciclo for NON acquisisce implicitamente StopIteration. Lo prende solo se viene lanciato dal prossimo metodo dell'iteratore, non se viene gettato nel corpo del ciclo. Nella tua domanda, csvreader.next() è analogo al corpo del ciclo. – Miles

-1

Se per qualsiasi motivo è necessario anche tenere traccia del numero di riga, vi consiglio:

rows = zip(xrange(20), csvreader) 

In caso contrario, è possibile striscia fuori dopo o ... beh, è meglio provare un'altra opzione più ottimale dall'inizio :-)

+0

Se hai bisogno del numero di riga, sicuramente dovresti usare enumerate() .. –

0

itertools.izip (2) fornisce un modo per semplificare le operazioni di comprensione delle liste, ma islice sembra essere la strada da percorrere in questo caso.

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

che ha il vantaggio che non si basa su len() (es. Per apsw.cursor) – Mark

+0

'enumerate' è il modo giusto per farlo , non zippare un raggio. – ArekBulski