"for line in x:" verhaspelt sich?

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
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

habe gerade zwei Stunden tot geschlagen, weil sich ein Skript verhaspelt hat. Der Code sah so aus:

Code: Alles auswählen

f = open(fname,rU)
for line in f:
     diverses Zeugs
Irgendwann bricht Python die Prozessierung meiner Daten in dem File (Format: csv) einfach ab (immer an der selben, unauffälligen, Stelle).
Wenn ich aber schreibe:

Code: Alles auswählen

for line in f.readlines():
funktioniert alles. (Bei xreadlines allerdings fliegt das Skript an der selben Stelle auf die Nase wie zuvor.)

Woran könnte das liegen? Jemand eine Idee?

Gruß,
Christian
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Ja. Du veränderst den Filepointer in der Schleife, denn mit readlines() werden Zeilen alle direkt beim Laden gelesen, während mit xreadlines() und for l in f die Zeilen der Reihe nach gelesen werden, und zwar immer ab dem aktuellen Filepointer, aus dem Iterator.

Das ist wieder ein typischer Fall von "wir verändern das Objekt über das wir iterieren in der Schleife." Und das geht bei fast keinem Typ gut aus.
--- Heiko.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Danke. Hm, es klingt plausibel. Hätte ich also eine Kopie von line vor allem weiteren Schritten anlegen müssen, um dann mein .split() darauf anzuwenden ...
Gruß,
Christian
mr.hide
User
Beiträge: 108
Registriert: Montag 29. August 2005, 14:02

Hmmm, sehe ich das richtig, dass es prinzipiel möglich ist, direkt über das file zu iterieren?

Und der Fehler liegt dann daran, dass du in der Schleife etwas machst...?

Weil bei extrem großen Files ist es doch net so gut wenn man die komplett in eine Liste lädt...
Grüße
Matthias

- Fluchen befreit von Kummer und Leid -
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

Also was ist denn rU?

Code: Alles auswählen

f = open(fname,'r')
for line in f:
    l = line.split()
    print l
Sowas sollte ohne Probleme funktionieren.

Gruss
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

rayo hat geschrieben: Also was ist denn ru?
pydoc hat geschrieben: Add a 'U' to mode to open the file for input with universal newline support.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

mr.hide hat geschrieben:Weil bei extrem großen Files ist es doch net so gut wenn man die komplett in eine Liste lädt...
Stimmt... Würde mann dann nicht mit einer temp-Datei arbeiten? Oder die Original-Datei nach *.bak umbenennen, öffnen, iterieren, verändern und in neuer Datei schreiben...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Aber sollte das rU nicht ein String sein?
Und was passiert ohne U? (nur r)

Gruss
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Jep, es sollte ein String sein... Da ist ist der Code aus dem ersten Beitrag broken ;)

Ohne das "U" sind IMHO die Zeilenenden so wie in der Datei, somit sind nicht alle Varianten nach "\n" konvertiert...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

oh Gott, habe ich jetzt eine Grundsatzdiskussion auf dem Gewissen? :wink:
Natürlich ist es nicht so clever extrem große Dateien einzulesen, aber das ist hier nicht der Fall und es kratzt mich überhaupt nicht, daß ich nicht mit Kanonen auf Spatzen schießen muß ...

ad "rU": Das habe ich mir angewöhnt, weil immer wieder mal unter Windows genierierte Dateien auf meinem Rechner (Linux) landen.

ad rayos Bemerkung:
Sowas sollte ohne Probleme funktionieren.
Tja, das habe ich eben auch gedacht. Und das hat es auch immer getan - nur jetzt eben nicht. modelnine hat wohl den entscheidenden Hinweis gegeben: Irgendwo mache ich etwas mit "line", was ich nicht sollte - ungewollt, nota bene. Aber bevor ich diese Stelle jetzt gefunden und korrigiert habe ...

Gruß,
Christian
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Vielleicht liegt ja genau beim U das Problem, einfach mal testen, weil bis jetzt hatte ich nie Probleme eine Datei direkt mit for line in f: zu bearbeiten

gruss

*edit* Also line ist ja ein String und die sind unveränderbar, also darfst du mit dem machen was du willst, da sollte nichts passieren.

funktioniert denn:

Code: Alles auswählen

f = open(fName, 'rU')
for line in f:
    print line.split(' ')
f.close()
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

modelnine hat geschrieben:Das ist wieder ein typischer Fall von "wir verändern das Objekt über das wir iterieren in der Schleife." Und das geht bei fast keinem Typ gut aus.
Hi!

Wurde die Datei wirklich mit

Code: Alles auswählen

f = open(fname,rU)
geöffnet (sieht man von den fehlenden Anführungszeichen ab), dann ist die Datei "readonly". Zumindest kann dann dieses "File"-Objekt nicht für eine Änderung herangezogen werden. Egal was du mit diesem File-Objekt anstellst, es dürfte sich nicht verändern.

Anders sieht das natürlich aus, wenn du die Datei nicht mit "rU" öffnest und mit "write()" an das Ding ran gehst. Auch eine Änderung von einem anderen Programm aus ist nicht auszuschließen.

@CM: Kann es sein, dass sich die Datei in der Zwischenzeit ändert, oder ist das ausgeschlossen?

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Ja, es ist ausgeschlossen, daß die Datei in der Laufzeit des Skriptes geändert wird. Aber ansonsten sind Deine Einwände natürlich absolut richtig.
Aber ich werde mich erst wieder damit befassen, wenn ich etwas mehr Zeit habe - zur Zeit kommt mir mein Chef zu häufig mit "machen Sie doch mal schnell" ...
Gruß,
Christian
BlackJack

gerold hat geschrieben:Wurde die Datei wirklich mit

Code: Alles auswählen

f = open(fname,rU)
geöffnet (sieht man von den fehlenden Anführungszeichen ab), dann ist die Datei "readonly". Zumindest kann dann dieses "File"-Objekt nicht für eine Änderung herangezogen werden. Egal was du mit diesem File-Objekt anstellst, es dürfte sich nicht verändern.
Ganz egal ist das nicht. Wenn Du in einer Schleife über `f` iterierst, dann darfst Du innerhalb der Schleife aus `f` auch nichts lesen! Der Iterator über die Zeilen puffert nämlich und wenn Du dann innerhalb der Schleife liest, dann ist das nicht die nächste Zeile nach `line` sondern kann eine spätere Zeile, oder auch nur ein Teil (das Ende) davon sein.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

BlackJack hat geschrieben:
gerold hat geschrieben:Wurde die Datei wirklich mit

Code: Alles auswählen

f = open(fname,rU)
geöffnet (sieht man von den fehlenden Anführungszeichen ab), dann ist die Datei "readonly". Zumindest kann dann dieses "File"-Objekt nicht für eine Änderung herangezogen werden. Egal was du mit diesem File-Objekt anstellst, es dürfte sich nicht verändern.
Ganz egal ist das nicht. Wenn Du in einer Schleife über `f` iterierst, dann darfst Du innerhalb der Schleife aus `f` auch nichts lesen! Der Iterator über die Zeilen puffert nämlich und wenn Du dann innerhalb der Schleife liest, dann ist das nicht die nächste Zeile nach `line` sondern kann eine spätere Zeile, oder auch nur ein Teil (das Ende) davon sein.
Hi BlackJack!

Ich habe das jetzt mal ohne Kürzung oben stehen lassen. -- :twisted: Dir ist schon klar, dass ich kein Wort verstanden habe, oder? :shock:

Der einzige Grund, weshalb ich mit

Code: Alles auswählen

for line in f:
über ein File-Objekt iterieren möchte ist, dass ich Zeile für Zeile lesen möchte. Jetzt sagst du mir, dass man das nicht darf. Ich bin jetzt ein wenig -- nein stimmt nicht -- total verwirrt. :D

Ich weiß, dass du das nicht so gemeint hast, aber schlau werde ich daraus trotzdem nicht. :oops:

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Was ich in meinem ursprünglichen Post sagte und was jetzt auch wieder gemeint wurde:

Code: Alles auswählen

for l in f:
   print l
   print f.read(5)
ist böse, weil ich innerhalb der Schleife das Objekt über das ich iteriere (also f) verändere.

Code: Alles auswählen

for l in f:
    l = "blah"
    l += "blubb"
ist nicht böse, weil ich das Objekt über das ich iteriere in der Schleife nicht verändere.

Vergleiche mit:

Code: Alles auswählen

l = ["blah","blubb","gaga"]
for pos, item in enumerate(l):
    print pos, item
    del l[pos]
print l
Auch hier ändere ich wieder das Objekt über das ich iteriere, und auch hier passieren böse Dinge.

Alles klar? ;-)
--- Heiko.
Antworten