2015-12-16 12 views
9

Mein Generator sieht wie folgt aus:Wie in CSV-Datei von einem Generator in Python schreiben

def mygen(reader): 
    for row in reader: 
     yield row[0],row[1],row[2],row[3],row[4] 

Ich versuche, diesen Generator erzeugten Werte in folgenden Weise einzufügen:

file1=open(f2,"w") 
writes=csv.writer(file1,delimiter=' ',quoting=csv.QUOTE_ALL) 
g=mygen(reader) 
for x in g: 
    writes.writerow([x]) 

Es fügt leere Zeilen in die Datei ein, ohne eine Ausgabe zu erzeugen. Es funktioniert perfekt, wenn ich denselben Generator verwende, um Code in eine Tabelle einzufügen.

+0

Es wäre nicht hinzufügen leere Zeilen; sagst du * werden überhaupt keine Zeilen * hinzugefügt? Stellen Sie sicher, dass Sie "Reader" nicht separat verwendet haben, bevor Sie es in "mygen()" verwenden. –

+0

Genau das ist passiert. Ich habe es früher auch benutzt. Vielen Dank. Aber bitte sag mir warum der Grund? –

+1

Dateiobjekte verfügen über einen Dateizeiger, der angibt, von wo aus gelesen oder in den nächsten geschrieben werden soll. Jedes Mal, wenn Sie Daten lesen, bewegt sich dieser Zeiger vorwärts. Sobald Sie alle Daten gelesen haben, befinden sie sich am Ende der Datei, und weitere Leseversuche geben keine Daten zurück (es sei denn, Sie fügen der Datei Daten hinzu). –

Antwort

9

Ihre x ist bereits eine Sequenz, die Sie nicht in einer Liste wickeln müssen:

for x in g: 
    writes.writerow(x) 

Sie könnten nur Ihr Generator direkt an writes.writerows() passieren:

with open(f2, "w") as file1: 
    writes = csv.writer(file1, delimiter=' ', quoting=csv.QUOTE_ALL) 
    writes.writerows(mygen(reader)) 

Demo:

>>> import sys 
>>> import csv 
>>> def mygen(reader): 
...  for row in reader: 
...   yield row[0],row[1],row[2],row[3],row[4] 
... 
>>> reader = csv.reader('''\ 
... foo,bar,baz,spam,ham,eggs 
... 42,81,13,97,73,100 
... '''.splitlines()) 
>>> writes = csv.writer(sys.stdout, delimiter=' ', quoting=csv.QUOTE_ALL) 
>>> writes.writerows(mygen(reader)) 
"foo" "bar" "baz" "spam" "ham" 
"42" "81" "13" "97" "73" 

Sie müssen aufpassen, dass Ihre reader ist kein Generator, den du schon erschöpft hast. Wenn es sich um ein Objekt csv.reader() handelt und Sie alle Zeilen zuvor gelesen haben, müssen Sie das zugrunde liegende Dateiobjekt erneut mit fileobj.seek(0) an den Anfang zurückführen. Es wäre jedoch besser, die Datei nicht zweimal lesen zu müssen.

Wenn Ihr reader Objekt erzeugt Sequenzen (wie Listen oder Tupel), könnten Sie einfach schneiden verwenden, um die ersten 5 Elemente zu bekommen, keine Notwendigkeit, jeden einzelnen Index tippen:

def mygen(reader): 
    for row in reader: 
     yield row[:5] 
+0

Ich habe den Schnitt gemacht. Gleiche Ergebnisse wie zuvor! –

+1

@ParisaRai: Bei einem * frischen * 'Leser'-Objekt, das Zeilen erzeugt, funktioniert der Code einwandfrei. –

+0

Das hat funktioniert. Danke vielmals –