2012-04-04 5 views
5

Ich dachte immer über eine Datei-wie in Python iterieren wäre gleichbedeutend mit dem Aufruf seiner readline Methode in einer Schleife, aber heute habe ich eine Situation, wo das nicht wahr ist. Insbesondere habe ich eine Popen ‚d Prozess p woUnterschied zwischen Iterieren über eine Datei und Aufruf von Readline

list(itertools.takewhile(lambda x: x != "\n", 
         p.stdout)) 

hängt (vermutlich weil p wartet auf die Eingabe, die beide stdin und stdout sind Rohre meiner Python-Verfahren), während die folgende Arbeiten:

list(itertools.takewhile(lambda x: x != "\n", 
         iter(p.stdout.readline, ""))) 

Kann jemand den Unterschied erklären?

+0

Seitennotiz: Anstelle von 'fiter()' können Sie 'iter (f.readline, None)' oder sogar 'iter (f.readline," \ n ")' 'takewhile()' ersetzen. –

+0

Das Problem, das Sie sehen, hängt mit der Pufferung zusammen: 'file .__ iter __()' macht irgendwie aggressivere Pufferung als 'file.readline()' - deshalb können Sie sie auch nicht mischen. Zu faul, um die Details zu recherchieren und dies in eine Antwort im Moment zu verwandeln ... –

+0

@SvenMarnach: du meinst 'iter (f.readline," ")', aber ja, danke, ich vergesse das immer wieder :) –

Antwort

4

Der Unterschied liegt rein in der Implementierung der Iteration gegenüber der readline Methode. Die Datei-Iteration liest Blöcke (standardmäßig 8 Kilobyte) ein und teilt den Puffer dann in Zeilen auf, wenn Sie sie verbrauchen. Die Methode readline dagegen kümmert sich darum, nie mehr als eine Zeile zu lesen, und das bedeutet Zeichen für Zeichen zu lesen. Das Lesen in Blöcken ist viel effizienter, aber es bedeutet, dass Sie andere Operationen in der Datei nicht zwischen Lesevorgängen mischen können. Die Erwartung ist, dass Sie beim Iterieren der Datei alle Zeilen der Reihe nach lesen und keine anderen Operationen ausführen. Die readline Methode kann diese Annahme nicht machen.

Als Sven Marnach deutete in seinem Kommentar zu Ihrer Frage, Sie iter(f.readline, '') verwenden einen Iterator zu erhalten, die Zeilen aus der Datei liest ohne auf Kosten der Leistung in Blöcken, zu lesen.

+0

Wissen Sie, wo im CPython-Quellcode ich die Implementierung von Datei-Iteratoren finde? –

+0

In 'Objekte/Dateiobjekt.c'. Dateiobjekte sind ihre eigenen Iteratoren, daher gibt es keinen separaten Typ. 'file.readline' ist' file_readline', und die Iteration erfolgt über 'file_iternext'. –