2009-07-09 7 views
9

Ich mag würde höchstens 20 Zeilen aus einer CSV-Datei lesen:Python: StopIteration Ausnahme und Listenkomprehensionen

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

funktioniert gut, wenn die Datei 20 oder mehr Zeilen enthält, schlägt mit einer StopIteration Ausnahme anders.

Gibt es eine elegante Möglichkeit, mit einem Iterator umzugehen, der eine StopIteration-Exception in ein Listenverständnis werfen könnte, oder sollte ich eine reguläre for-Schleife verwenden?

Antwort

11

Sie können itertools.islice verwenden. Es ist die Iterator-Version von List Slicing. Wenn der Iterator weniger als 20 Elemente enthält, werden alle Elemente zurückgegeben.

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

Danke Ayman. Es sieht so aus, als müssten Listenübersichten aktualisiert werden, um mit StopIteration fertig zu werden, nein? Es scheint, dass "für" bereits aktualisiert wurde, um damit fertig zu werden (es hört auf zu iterieren, wenn es auf die Ausnahme trifft, implizit abfängt), und ich sehe keinen offensichtlichen Grund dafür, dass Listenergänzungen nicht dasselbe tun. – Parand

+2

fängt die StopIteration relativ zu ihrer iterablen, nicht zu anderen solchen Objekten in ihrer Suite ab. Zum Beispiel c = iter (Bereich (5)) für i im Bereich (10): \t Druck i, c.next() die StopIteration Ausnahme relativ zu c erhöhen. – Mapio

+3

Eine for-Schleife fängt StopIteration NICHT implizit auf. Es fängt es nur ab, wenn es von der nächsten Methode des Iterators ausgelöst wird, nicht wenn es in den Schleifenkörper geworfen wird. In Ihrer Frage entspricht csvreader.next() dem Schleifenkörper. – Miles

-1

Wenn Sie aus irgendeinem Grund auch den Überblick über die Zeilennummer zu halten brauchen, ich Ihnen empfehlen würde:

rows = zip(xrange(20), csvreader) 

Wenn nicht, können Sie es Streifen aus nach oder ... na ja, Sie würden besser andere Option mehr optimal von Anfang an versuchen :-)

+0

Wenn Sie die Zeilennummer benötigen, sollten Sie sicher enumerate() verwenden. –

0

itertools.izip (2) bietet eine Möglichkeit, auf einfache Weise Listenkomprehensionen arbeiten, machen aber islice sieht der Weg, um in diesem Fall zu gehen.

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

das hat den Vorteil, dass es nicht len ​​() (zB für apswcursor) – Mark

+0

'enumerate' ist der richtige Weg, es zu tun , kein Zippen eines Bereichs. – ArekBulski