Отключить буферизацию

Где буфер в этом следующем... и как его отключить?

Я пишу в stdout в python-программе, например:

for line in sys.stdin:
    print line

Здесь происходит буферизация:

tail -f data.txt | grep -e APL | python -u Interpret.py

Я попробовал следующее, чтобы избавиться от возможной буферизации... без везения:

  • как указано выше, используя флаг -u с вызовом python
  • вызов sys.stdout.flush() после каждого вызова sys.stdout.write() ... все они создают буферизованный поток с python, который ждет что-то вроде минуты, чтобы распечатать первые несколько строк.
  • использовалась следующая измененная команда:

    stdbuf -o0 tail -f data.txt | stdbuf -o0 -i0 grep -e APL | stdbuf -i0 -o0 python -u Interpret.py

Чтобы оценить мои ожидания, я попытался:

tail -f data.txt | grep -e APL 

Это создает устойчивый поток строк... это, безусловно, не так буферизуется, как команда python.

Итак, как отключить буферизацию? ОТВЕТ: Оказывается, на обоих концах трубы есть буферизация.

Ответ 1

Проблема, я считаю, в grep буферизации ее вывода. Он делает это, когда вы нажимаете tail -f | grep ... | some_other_prog. Чтобы получить grep для очистки один раз в строке, используйте параметр --line-buffered:

% tail -f data.txt | grep -e APL --line-buffered | test.py
APL

APL

APL

где test.py:

import sys
for line in sys.stdin:
    print(line)

(Проверено на linux, gnome-terminal.)

Ответ 2

file.readlines() и for line in file имеют внутреннюю буферизацию, на которую не влияет опция -u (см. - примечание о опции u). Используйте

while True:
   l=sys.stdin.readline()
   sys.stdout.write(l)

вместо.

Кстати, sys.stdout по умолчанию буферизируется по строке, если он указывает на терминал, а sys.stderr небуферируется (см. stdio buffering).

Ответ 3

Проблема в вашем цикле for. Он будет ждать EOF, прежде чем продолжить. Вы можете исправить это с помощью кода вроде этого.

while True:
    try:
        line = sys.stdin.readline()
    except KeyboardInterrupt:
        break 

    if not line:
        break

    print line,

Попробуйте это.

Ответ 4

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) и убедитесь, что PYTHONUNBUFFERED установлен в вашей среде.