python — общение с долго запущенным дочерним процессом через stdin и stdout

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

Я пытаюсь запустить длительный дочерний процесс, такой как REPL (lein repl, python), и связаться с ним через stdin / stdout. Я нашел много примеров того, как это сделать, когда родитель только один раз пишет дочернему элементу, а затем читает некоторые входные данные, но я не могу понять, как это сделать, где я могу писать и читать в / из дочернего процесса ‘stdin / stdout в течение неопределенного периода времени, как это было бы с сокетом TCP.

В идеале я пытаюсь сделать это в Python, но я не против увидеть, как это сделать на C или C ++. Я наткнулся на библиотеку под названием pexpect (https://pexpect.readthedocs.org/en/latest/), что близко к тому, что я ищу, но, похоже, оно предназначено для того, чтобы убедиться, что дочерний процесс работает, как ожидалось, или передать управление терминалом новому процессу, а не двунаправленной связи. Я также заметил Python Twisted, но документы немного плотные, и я до сих пор не могу сказать, может ли он сделать то, что я ищу

Редактировать: вот какой-то код у меня сейчас

from subprocess import Popen, PIPE

p = Popen('lein repl 1>&2', shell=True, stderr=PIPE)

# p.communicate('(print "Hello, world!")')[0]

for line in iter(p.stderr.readline, b''):
print('my-repl>> ' + line)
# p.stderr.flush()print 'End of script'

Этот код запустит программу и позволит мне напрямую взаимодействовать с ней. Однако когда я добавляю stdin = PIPE, программа зависает. Если я добавлю stdin = PIPE и попытаюсь вызвать p.communicate, я получу ошибку

ValueError: I/O operation on closed file

Редактировать 2: некоторый рабочий код. Он читает 10 строк (текущее число, выводимое nREPL при запуске), затем записывает строку, затем читает две строки.

из подпроцесса импорт Popen, ТРУБА

# Whether to use stdout or stderr as the output stream
# for the child process
proc_use_stderr = False

# Process Variables
p = None
p_out = None
p_in = None
# Config
nrepl_num_start_lines = 11

if proc_use_stderr:
p = Popen('lein repl 1>&2', shell=True, stderr=PIPE, stdin=PIPE)
p_out = p.stderr
else:
p = Popen(['lein', 'repl'], stdout=PIPE, stdin=PIPE)
p_out = p.stdout

p_in = p.stdin

child_output_lines = []
for i in range(0, nrepl_num_start_lines):
child_output_lines.append(p_out.readline().strip('\n'))

# Leads to: ValueError: I/O operation on closed file
# p.communicate('(print "Hello, repl!")\n')[0]
p_in.write('(print "Hello, repl!")\n')
p_in.flush()

print 'Starting readline'
child_output_lines.append(p_out.readline().strip('\n'))
child_output_lines.append(p_out.readline().strip('\n'))
print 'Ending readline'

for i in range(0, len(child_output_lines)):
print i, ':', child_output_lines[i]

# TODO: Terminal gets all goofy after the process exits
# p.stderr.flush()
# p.stderr.close()
p_out.flush()
p_out.close()
p_in.flush()
p_in.close()
p.terminate()

print 'Summary:'
print 'Num Received Lines:', len(child_output_lines)
print 'Line List:', child_output_lines
print 'End of script'

2

Решение

Задача ещё не решена.

Другие решения