Почему python продолжает буферизовать стандартный вывод даже при сбросе и использовании -u? - PullRequest
3 голосов
/ 02 ноября 2011
$ cat script.py
import sys

for line in sys.stdin:
    sys.stdout.write(line)
    sys.stdout.flush()

$ cat script.py - | python -u script.py

Вывод правильный, но он начинает печататься только после того, как я нажму Ctrl-D, тогда как следующее начинает печататься сразу:

$ cat script.py - | cat

, что привело меня к мысли, что буферизация не исходит отcat.

Мне удалось заставить его работать, выполнив:

for line in iter(sys.stdin.readline, ""):

, как объяснено здесь: Потоковые каналы в Python , но я не понимаю, почему первоеРешение не работает, как ожидалось.

Ответы [ 2 ]

4 голосов
/ 02 ноября 2011

Страница руководства Python раскрывает ответ на ваш вопрос:

   -u     Force stdin, stdout and stderr to be totally unbuffered.  On systems where it matters, also put stdin, stdout and stderr in binary mode.  Note that
          there  is  internal  buffering  in  xreadlines(),  readlines()  and file-object iterators ("for line in sys.stdin") which is not influenced by this
          option.  To work around this, you will want to use "sys.stdin.readline()" inside a "while 1:" loop.

То есть виновата внутренняя буферизация итераторов файловых объектов (и она не исчезает с -u).

1 голос
/ 02 ноября 2011

cat блокирует буферизацию по умолчанию, если вывод на канал.Поэтому, когда вы включаете - (stdin) в команду cat, она ожидает получения EOF (ваш ctrl-D закрывает поток stdin) или 8K (возможно) данных перед выводом чего-либо.

Если вы измените catкоманда "cat script.py |"вы увидите, что все работает так, как вы ожидали.

Кроме того, если вы добавите 8K комментариев в конец файла script.py, он сразу же напечатает его.

Редактировать:

Вышесказанное неверно.: -)

Оказывается, что file.next () (используется файловыми итераторами, т. Е. Для строки в файле) имеет скрытый буфер опережающего чтения, который не используется readline (), который просто читаетсимвол, пока он не увидит новую строку или EOF.

...