2009-07-09 10 views
9

que me gustaría leer como máximo 20 líneas de un archivo csv:Python: StopIteration de excepción y las listas por comprensión

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

funciona bien si el archivo tiene 20 o más filas, falla con una excepción StopIteration lo contrario.

¿Existe una forma elegante de tratar con un iterador que podría lanzar una excepción StopIteration en una lista de comprensión o debería usar un ciclo for para regular?

Respuesta

11

Puede usar itertools.islice. Es la versión iterativa de la división de listas. Si el iterador tiene menos de 20 elementos, devolverá todos los elementos.

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

Gracias Ayman. Parece que las listas de comprensión deben actualizarse para tratar con StopIteration, ¿no? Parece que "para" ya se ha actualizado para tratarlo (deja de iterar cuando encuentra la excepción, atrapándolo implícitamente), y no veo una razón obvia para que las listas de comprensión no hagan lo mismo. – Parand

+2

para captura la StopIteration relativa a su iterable, no a otros objetos de este tipo en su suite. Por ejemplo c = iter (intervalo (5)) para i en el rango de (10): \t impresión i, c.next() elevará la excepción StopIteration relación a c. – Mapio

+3

Un ciclo for NO captura implícitamente StopIteration. Solo lo atrapa si es lanzado por el siguiente método del iterador, no si es arrojado al cuerpo del bucle. En su pregunta, csvreader.next() es análogo al cuerpo del bucle. – Miles

-1

Si por cualquier razón usted necesita también para realizar un seguimiento del número de línea, me gustaría recomendar que:

rows = zip(xrange(20), csvreader) 

Si no es así, se puede despojar a cabo después o ... bueno, es mejor que intentar otra opción más óptima desde el principio :-)

+0

Si necesita el número de línea, seguramente debe usar enumerate() .. –

0

itertools.izip (2) proporciona una manera fácil de hacer listas por comprensión funcionan, pero islice parece ser el camino a seguir en este caso.

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

que tiene la ventaja de que no se basa en len() (por ejemplo, para apsw.cursor) – Mark

+0

'enumerar' es la forma correcta de hacerlo , sin comprimir un rango. – ArekBulski

Cuestiones relacionadas