Python Popen().stdout.read() зависает

Я пытаюсь получить вывод другого скрипта, используя Python subprocess.Popen, как показано ниже.

process = Popen(command, stdout=PIPE, shell=True)
exitcode = process.wait()
output = process.stdout.read()   # hangs here

Он зависает на третьей строке, только когда я запускаю его как скрипт python, и я не могу воспроизвести это в оболочке python.

Другой сценарий печатает всего несколько слов, и я предполагаю, что это не проблема с буфером.

Кто-нибудь знает, что я здесь делаю неправильно?


person lyomi    schedule 21.01.2013    source источник
comment
И если вы запустите команду в command вручную, она сгенерирует вывод?   -  person Some programmer dude    schedule 21.01.2013


Ответы (3)


Вероятно, вы захотите использовать .communicate() вместо .wait() плюс .read() . Обратите внимание на предупреждение о wait() на странице документации subprocess:

Предупреждение Это приведет к тупику при использовании stdout=PIPE и/или stderr=PIPE, и дочерний процесс генерирует достаточно вывода в канал, чтобы он блокировал ожидание буфера канала ОС для приема дополнительных данных. Используйте communicate(), чтобы избежать этого.

http://docs.python.org/2/library/subprocess.html#subprocess.Popen.wait

person Amber    schedule 21.01.2013
comment
Спасибо за ответ. Я только что понял, что прочитал эту часть документации. Что я делал, так это извлекал стандартный вывод в режиме реального времени в цикле while process.poll() is None: во время работы скрипта, а приведенный выше код был урезанной версией. Но я предполагаю, что он зависал из-за аналогичной проблемы с тупиком ... - person lyomi; 21.01.2013
comment
хм, у меня не сработало, все равно зависает - person CrazyVideoGamer; 06.01.2021

read() ожидает EOF перед возвратом.

Вы можете:

  • подождите, пока подпроцесс умрет, тогда read() вернется.
  • используйте readline(), если ваш вывод разбит на строки (все равно будет зависать, если нет строк вывода).
  • используйте os.read(F,N), который возвращает не более N байтов из F, но все равно будет блокироваться, если канал пуст (если только для fd не установлено значение O_NONBLOCK).
person aaa90210    schedule 14.11.2017

Вы можете увидеть, как бороться с зависанием чтения stdout/stderr в следующих источниках:

процесс чтения

person sergzach    schedule 23.03.2019