Задача, которую я пытаюсь выполнить, - передать файл ruby в потоковом режиме и распечатать выходные данные. (ПРИМЕЧАНИЕ: я не хочу распечатывать все сразу)
while proc.poll() isNone: data = stdout.readline() if data != "": print(data) else: break
print("This is never reached!")
ruby_sleep.rb
puts "hello"
sleep 2
puts "goodbye!"
Проблема
Потоковая передача файла работает нормально. Выходные данные hello / goodbye выводятся с задержкой в 2 секунды. Именно так и должен работать скрипт. Проблема в том, что readline() зависает в конце и никогда не завершается. Я никогда не добираюсь до последней печати.
Я знаю, что здесь много подобных вопросов, связанных с stackoverflow, но ни один из них не заставил меня решить проблему. Я не разбираюсь во всем этом подпроцессе, поэтому, пожалуйста, дайте мне более практический / конкретный ответ.
С уважением
Редактировать
Исправлен непреднамеренный код. (ничего общего с фактической ошибкой)
Поскольку псевдотерминальная обработка сильно зависит от платформы, существует код для ее выполнения только для Linux. (Предполагается, что код Linux должен работать на других платформах, но он еще не тестировался.)
Неясно, насколько хорошо он работает в других операционных системах.
# Wait until we've processed all output reader.join()
print"Done!"
Обратите внимание, что у меня не установлен Ruby, и, следовательно, я не могу проверить вашу реальную проблему. Хотя с ls работает нормально.
Ответ 3
По сути, то, на что вы смотрите здесь, - это состояние гонки между вашим proc.poll() и вашим readline(). Поскольку входные данные в master дескрипторе файла никогда не закрываются, если процесс попытается выполнить readline() над ним после завершения вывода процесса ruby, читать будет нечего, но канал никогда не закроется. Код будет работать только в том случае, если процесс оболочки закроется до того, как ваш код попробует другой readline().
Вот временная шкала:
readline() print-output poll() readline() print-output (last line of real output) poll() (returns false since process isnot done) readline() (waits for more output) (process is done, but output pipe still openand no poll ever happens for it).
Простое решение - просто использовать модуль подпроцесса, как предлагается в документации, а не в сочетании с openpty:
proc = Popen(command, bufsize=0, shell=True, stdout=PIPE, close_fds=True) for line in proc.stdout: print line
print("This is most certainly reached!")
As others have noted, readline() will block when reading data. It will even do so when your child process has died. I am not sure why this does not happen when executing ls as in the other answer, but maybe the ruby interpreter detects that it is writing to a PIPE and therefore it will not close automatically.