zeilenweises einlesen+veraendern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
silky vanilla
User
Beiträge: 51
Registriert: Donnerstag 3. Mai 2007, 09:46

silky vanilla hat geschrieben:Ich moechte eine Datei Zeile fuer Zeile einlesen. Dabei moechte ich aber nach jedem einlesen von einer Zeile diese splitten und Element fuer Element auf bestimmte Bedingungen ueberpruefen. Sind alle Bedingungen war, soll diese Zeile geloescht werden. Dann moechte ich in die naechste Zeile springen usw.

Eine Zeile einlesen mit
Ich dachte mir, dass ich das ganze Prozedere in einer for-Schleife ablaufen lassen koennte

Code: Alles auswählen

for line in inp:
   line = inp.readline()
   parts = line.split()
   if parts[2]== Bedingung and parts[3]== Bedingung...
Doch wenn ich das so mach kommt eine Fehlermedung:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/cellnet/claudiak/human_network/e.py", line 9, in <module>
    line = inp.readline()
ValueError: Mixing iteration and read methods would lose data
Kann mir jemand weiter helfen? Was gibt es sonst fuer Loesungen?
Zuletzt geändert von silky vanilla am Freitag 22. Juni 2007, 12:31, insgesamt 1-mal geändert.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

mit inp.readline() iterierst du innerhalb einer Iteration per for-Schleife.
Wenn die Dateien nicht allzu groß sind dann kannst du einfach so iterieren

Code: Alles auswählen

f = open("test.txt")
for line in f:
 print line
silky vanilla
User
Beiträge: 51
Registriert: Donnerstag 3. Mai 2007, 09:46

Die Dateien sind sehr gross :shock:
BlackJack

@silky vanilla: Die Ausnahme sagt ,dass Du über die Datei iterierst und gleichzeitig *nochmal* Zeilen aus der Datei liest. Die ``for line in inp``-Schleife liest schon Zeile für Zeile ein und bindet jede Zeile an den Namen `line`. Wozu soll dann das ``inp.readline()`` in der Schleife gut sein? Wenn es so funktionieren *würde* wie man sich das intuitiv vorstellt, dann würde die Schleife nur jede zweite Zeile verarbeiten.

Zeilen löschen in Textdateien ist nur unter grossem Aufwand möglich. Wesentlich einfacher und sicherer, zum Beispiel wenn mittendrin das Programm mit einem Fehler abbricht, ist es eine neue Datei zu schreiben und dort einfach die unerwünschten Zeilen auszulassen. Am Ende kann man dann die neue Datei zur alten umbenennen.
silky vanilla
User
Beiträge: 51
Registriert: Donnerstag 3. Mai 2007, 09:46

Hier habe ich jetzt auch ein kleines Skript, welches eigentliche alle die Zeilen loeschen soll, in denen in den Spalten nur 'NA' oder '0' steht. Mit Ausnahmen von Spalte 3, da gilt es nur fuer 'NA'.
Es kommt keine Fehlermeldung, es loescht aber auch die jeweiligen Zeilen nicht, Es gibt mir die Datei genauso wie sie vorher war wieder aus.
Wo koennte der Fehler liegen???
Hier das Skript

Code: Alles auswählen

inp = open('fuer f.tab','r')
out = open('ohne komplette na.tab','w')

for line in inp:
    data = line.split()
    if data[2] == 'NA' and data[3] =='NA' or '0' and data[4] == 'NA' or '0' and data[5] == 'NA' or '0' and data[6] == 'NA' or '0' and data[7] == 'NA' or '0' and data[8] == 'NA' or '0' and data[9] == 'NA' or '0' and data[10] == 'NA' or '0' and data[11] == 'NA' or '0' and data[12] == 'NA' or '0':
        del data


    out_line = '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' % (data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9],data[10],data[11],data[12])

    out.write(out_line)
    
inp.close()
out.close()
BlackJack

``obj == 'NA' or '0'`` tut nicht das was Du denkst was es tut. Das wird so geklammert: ``(obj == 'NA') or '0'`` und das ist immer wahr weil entweder der Vergleich schon wahr ist, oder eben '0' wahr ist. Ausser bei der leeren Zeichenkette gilt `bool(s) == True`.

Code: Alles auswählen

In [6]: 'NA' == 'NA' or '0'
Out[6]: True

In [7]: 'Quark' == 'NA' or '0'
Out[7]: '0'

In [8]: bool('Quark' == 'NA' or '0')
Out[8]: True
Wenn die ``if``-Abfrage funktionieren würde käme das nächste Problem: ``del data`` löscht den *Namen* `data` auf den in Zeile 10 Zugegriffen wird -> `NameError`.

Wenn die Zeile nicht geschrieben werden soll, dann darf `out.write()` gar nicht erst aufgerufen werden.

Statt die Zeile mit so viel Schreibarbeit zusammenzusetzen könnte man auch die `str.join()`-Methode benutzen, oder gleich `line` in die Datei schreiben. Man hat die Zeile ja noch völlig unverändert zur Hand.

Überhaupt sollte man soviel Schreibarbeit durch Code ersetzen. Bis auf ``data[2]`` werden alle folgenden Elemente ja auf das gleiche Kriterium getestet, das schreit förmlich nach einer Schleife.

Falls man ``data[2]`` auch gegen '0' prüfen darf, könnte die ``if``-Anweisung so aussehen:

Code: Alles auswählen

    if False in (item in ('NA', '0') for item in data[2:]):
        out.write(line)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Nur mal so als Vereinfachung:

Code: Alles auswählen

out_line = "\t".join(x) + "\n"
Nun zu deinem Problem:

Code: Alles auswählen

data[3] =='NA' or '0'
bedeutet nicht data[3] gleich NA oder 0, sondern einfach nur data[3] gleich NA. Das '0' wird hier zu True. Was du meinst ist sicherlich:

Code: Alles auswählen

data[3] =='NA' or data[3] =='0'
Du solltest dein ganzes if-Konstrukt nochmal überdenken. Da kann man das meiste zusammenfassen und z lang ist die Zeile auch noch.

Wenn die Bedingung dann mal wahr wird, wird dir das 'del data' Schwierigkeiten machen. Das löscht nämlichen den Namen 'data', in der nächste Zeile wird dieser aber verwendet! Schau dir in der Doku mal die Hilfe zum Statement 'continue' an, oder noch besser: Stelle die if-Abfrage so um, dass die Ausgabe nur geschieht, wenn die Bedingung 'False' ist.

Edit: Ja ja, das Leben ist wie ein Tennisball :D Eine Minute später gepostet und nahezu der selbe Inhalt...
silky vanilla
User
Beiträge: 51
Registriert: Donnerstag 3. Mai 2007, 09:46

Vielen Dank fuer eure Muehen, das klappt jetzt alles... :D
Antworten