2012-04-28 2 views
7

Я пытаюсь поговорить с дочерним процессом, используя вызов subprocess.popen() python. В моем реальном коде я реализую тип IPC, поэтому я хочу написать некоторые данные, прочитать ответ, написать еще несколько данных, прочитать ответ и так далее. Из-за этого я не могу использовать Popen.communicate(), который в противном случае хорошо работает для простого случая.Чтение/запись в подпроцесс Popen()

Этот код показывает мою проблему. Он даже не получает первого ответа, зависает при первом «результате чтения». Зачем? Как я могу сделать эту работу, как я ожидаю? Выход

import subprocess 
p = subprocess.Popen(["sed", 's/a/x/g'], 
        stdout = subprocess.PIPE, 
        stdin = subprocess.PIPE) 

p.stdin.write("abc\n") 
print "Reading result:" 
print p.stdout.readline() 

p.stdin.write("cat\n") 
print "Reading result:" 
print p.stdout.readline() 

ответ

4

Я бы постарался использовать Popen().communicate(), если вы можете, так как для вас много приятных вещей, но если вам нужно использовать Popen() точно так, как вы описали, вам нужно установить sed, чтобы сбросить его буфер после строк новой строки с помощью -l вариант:

p = subprocess.Popen(['sed', '-l', 's/a/x/g'], 
        stdout=subprocess.PIPE, 
        stdin=subprocess.PIPE) 

и ваш код должен работать нормально

+1

Действительно, он работает! Мой sed почему-то использует -u для «небуферизованного», а не -l, но он работает все равно. Это решает мой примерный код, но, к сожалению, не мой настоящий код, так как фактическая команда не sed, а другая программа python. Хороший ответ, хотя, вы точно определили проблему. –

+1

Yup, проблема решена. Проблема заключалась в выводе буферизации результата. Выполнение простой stdout.flush() в моем подпроцессе решило проблему. Благодаря! –

3

sed «ы буферизуется и только выводит свои данные до тех пор, пока достаточно было совмещаться или входной поток исчерпан и закрыт.

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

import subprocess 
p = subprocess.Popen(["sed", 's/a/x/g'], 
        stdout = subprocess.PIPE, 
        stdin = subprocess.PIPE) 

p.stdin.write("abc\n") 
p.stdin.write("cat\n") 
p.stdin.close() 

print "Reading result 1:" 
print p.stdout.readline() 

print "Reading result 2:" 
print p.stdout.readline() 

Имейте в виду, что это не может быть сделано надежно, какие огромные данные в виде wriring в stdin блоков когда буфер заполнен. Лучший способ сделать это - использовать communicate().

+0

Но СЭД не действует таким образом при выполнении команды в оболочке непосредственно. Если вы это сделаете, ответ появится после каждой строки. И проблема остается, даже если я назову p.stdin.flush() после записи. Кроме того, в реальной жизни я написал также вызванную программу, нет буферизации, и она ведет себя одинаково. Я не уверен, что проблема буферизации здесь. –

+2

Ах, вы были правы, буферизация действительно была проблемой. –

Смежные вопросы