Pierwszy problem polega na tym, że readlines
odczytuje wszystkie linie na liście. Nie można tego zrobić, dopóki wszystkie linie nie będą obecne, co nie będzie możliwe, dopóki stdin
nie osiągnie EOF.
Ale w rzeczywistości nie potrzebują listy z wierszami, tylko niektóre iterable linii. A plik taki, jak sys.stdin
, jest już taki, jak, taki, który jest iterowalny. I jest to leniwy, który generuje jedną linię na raz, gdy tylko są one dostępne, zamiast czekać na wygenerowanie ich wszystkich naraz.
Więc:
for line in sys.stdin:
print line
Kiedy znajdziesz się sięgając readlines
, należy zadać sobie pytanie, czy rzeczywiście jest to potrzebne. Odpowiedź brzmi: zawsze być nie. (No chyba, że chcesz wywołać to z argumentem lub z jakimś uszkodzonym obiektem nie podobnym do pliku.) Aby uzyskać więcej informacji, patrz: Readlines Considered Silly.
Ale tymczasem, tam sekund problem. Nie chodzi o to, że Python buforuje swój stdin
, czy też inny proces buforuje jego stdout
, ale iterator plików-obiektów sam wykonuje wewnętrzne buforowanie, które może (w zależności od platformy), ale na większości platform POSIX, zazwyczaj będzie) uniemożliwić ci dotarcie do pierwszej linii aż do EOF, lub przynajmniej do momentu odczytania wielu linii.
Jest to znany problem z Pythonem w wersji 2.x, który został naprawiony w 3.x, *, ale to nie pomaga, chyba że chcesz dokonać aktualizacji.
Rozwiązaniem jest wymieniona w docs linii poleceń i środowiska, w tym podręcznika na większości systemów, ale pochowany w środku -u
flag documentation:
Należy pamiętać, że istnieje wewnętrzny buforowanie w xreadlines() readlines() i iteratory obiektów-plików ("dla linii w sys.stdin"), na które ta opcja nie ma wpływu. Aby obejść to, będziesz chciał użyć "sys.stdin.readline()" wewnątrz pętli "while while".
Innymi słowy:
while True:
line = sys.stdin.readline()
if not line:
break
print line
Lub:
for line in iter(sys.stdin.readline, ''):
print line
Dla innego problemu, w this answer Alex Martelli zwraca uwagę, że zawsze można po prostu zignorować sys.stdin
i ponownie - fdopen
deskryptor pliku. Co oznacza, że dostajesz wrapper wokół POSIX-a fd zamiast uchwytu C stdio. Ale to nie jest konieczne ani wystarczające dla tego pytania, ponieważ problem nie dotyczy buforowania Cddio, ale sposób, w jaki buforuje file.__iter__
.
* Python 3.x nie używa już buforowanie biblioteki C stdio za; robi wszystko samodzielnie, w typach w module io
, co oznacza, że iterator może po prostu współużytkować ten sam bufor, którego używa sam obiekt pliku. Chociaż io
jest również dostępny w wersji 2.x, nie jest to domyślna funkcja dla open
-lub dla uchwytów plików stdio, dlatego nie pomaga tutaj.
'readlines()' zbiera wszystkie linie do listy. Nie można utworzyć listy, dopóki nie ma wszystkich linii. – Barmar
Warto przeczytać (a przynajmniej skimming): http://stupidpythonideas.blogspot.com/2013/06/readlines-considered-silly.html?m=1 –
Ups, abarnert pobił mnie. –