Как правилно да взаимодействаме с процес с помощта на модул за подпроцес

Имам проблеми с пренасочването на stdio на друга програма с помощта на модул за подпроцес. Самото четене от stdout води до увисване и Popen.communicate() работи, но затваря канали след четене/запис. Кой е най-лесният начин да приложите това?

Играех си с това на Windows:

import subprocess
proc = subprocess.Popen('python -c "while True: print \'Hi %s!\' % raw_input()"',
                        shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                        stderr=subprocess.STDOUT)
while True:
    proc.stdin.write('world\n')
    proc_read = proc.stdout.readline()
    if proc_read:
        print proc_read

person Ivan Baldin    schedule 14.01.2009    source източник
comment
Дубликат: stackoverflow.com/questions/163542/, stackoverflow.com/questions/295459/   -  person S.Lott    schedule 14.01.2009
comment
-u флаг ще го реши за подпроцес на Python. Има също pexpect, pty модули и unbuffer, stdbuf, script помощни програми, които могат да помогнат за коригиране на проблема с буферирането на блокове.   -  person jfs    schedule 22.05.2013


Отговори (1)


Не отговаря на 100% на вашия пример, но помага да се разбере основният проблем: Процес P стартира дъщерен C. Дете C записва нещо в своя stdout. stdout на C е тръба, която има буфер от 4096 символа и изходът е по-кратък от това. Сега C чака някакъв вход. За C всичко е наред.

P чака изхода, който никога няма да дойде, защото ОС не вижда причина да изчисти изходния буфер на C (с толкова малко данни в него). Тъй като P никога не получава изхода на C, той никога няма да напише нищо в C, така че C виси в очакване на входа от P.

Поправка: Използвайте flush след всеки запис в канал, принуждавайки операционната система да изпрати данните сега.

Във вашия случай добавянето на proc.stdin.flush() в главния цикъл while и sys.stdout.flush() в дъщерния цикъл след отпечатването трябва да реши проблема ви.

Трябва също така да помислите за преместване на кода, който чете от другия процес, в нишка. Идеята тук е, че никога не можете да знаете кога ще пристигнат данните и използването на нишка ви помага да разберете тези проблеми, докато пишете кода, който обработва резултатите.

На това място исках да ви покажа новата документация на Python 2.6, но тя също не обяснява проблема с промиването :( О, добре...

person Aaron Digulla    schedule 14.01.2009
comment
Добро обяснение. Ето още от pexpect документи: В: Защо просто не използвате тръба (popen())? - person jfs; 22.05.2013
comment
Pexpect docs е преместен: ето нова връзка - person jfs; 13.09.2016