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

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

12 голосов
/ 07 декабря 2011

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

Я пишу на стандартный вывод в программе на 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.

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

Ответы [ 4 ]

12 голосов
/ 07 декабря 2011

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

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

.

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

6 голосов
/ 07 декабря 2011

Проблема, я полагаю, заключается в 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.)

3 голосов
/ 07 декабря 2011

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

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

    if not line:
        break

    print line,

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

0 голосов
/ 07 декабря 2011

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

...