Python - простые строки чтения из трубы

Я пытаюсь читать строки из трубы и обрабатывать их, но я делаю что-то глупое, и я не могу понять, что. Продюсер будет продолжать производить линии на неопределенный срок, например:

producer.py

import time

while True:
    print 'Data'
    time.sleep(1)

Потребителю просто нужно периодически проверять строки:

consumer.py

import sys, time
while True:
    line = sys.stdin.readline()
    if line:
        print 'Got data:', line
    else:
        time.sleep(1)

Когда я запускаю это в оболочке Windows как python producer.py | python consumer.py, он просто спит навсегда (никогда, кажется, не получает данные?) Кажется, что проблема заключается в том, что продюсер никогда не заканчивается, поскольку, если я отправлю конечный объем данных то он отлично работает.

Как я могу получить данные, которые будут получены и отображаться для потребителя? В реальном приложении производитель - это программа на С++, над которой я не контролирую.

Ответы

Ответ 1

Некоторые старые версии Windows моделировали трубы через файлы (поэтому они были склонны к таким проблемам), но это не было проблемой через 10 лет. Попробуйте добавить

  sys.stdout.flush()

продюсеру после print, а также попытайтесь сделать файл stdout производителя небуферизованным (используя python -u).

Конечно, это не поможет, если у вас нет контроля над продюсером - если он слишком сильно загружает свой результат, вы все равно будете долго ждать.

К сожалению, хотя существует много подходов к решению этой проблемы в Unix-подобных операционных системах, таких как pyexpect, pexpect, exscript и paramiko, я сомневаюсь, что любой из них работает в Windows; если это действительно так, я бы попробовал Cygwin, что накладывает на Linux достаточно похожего шпона на Windows, что часто позволяет использовать Linux-подобных подходов в окне Windows.

Ответ 2

Это о I/O, который по умолчанию используется для буферизации с помощью Python. Передайте -u опции интерпретатору, чтобы отключить это поведение:

python -u producer.py | python consumer.py

Он исправляет проблему для меня.