У меня были некоторые похожие проблемы с межпроцессным взаимодействием на основе терминала, которые, казалось, не могли быть решены с помощью popen
(и др.). В итоге я узнал, как использовать pty
, читая источник pexpect , который содержит примеры того, как (и комментарии о том, почему) получить pty
для перехода через необходимые обручи.
В зависимости от ваших потребностей, конечно, вы также можете просто использовать pexpect!
Вот мясо того, что я использовал в своем собственном проекте. Обратите внимание, что я не проверяю, завершается ли дочерний процесс; Сценарий должен был работать как демон, управляющий длительным процессом Java, поэтому мне никогда не приходилось иметь дело с кодами состояния. Надеюсь, однако, это даст вам большую часть того, что вам нужно.
import os
import pty
import select
import termios
child_pid, child_fd = pty.fork()
if not child_pid: # child process
os.execv("/path/to/command", ["command", "arg1", "arg2"])
# disable echo
attr = termios.tcgetattr(child_fd)
attr[3] = attr[3] & ~termios.ECHO
termios.tcsetattr(child_fd, termios.TCSANOW, attr)
while True:
# check whether child terminal has output to read
ready, _, _ = select.select([child_fd], [], [])
if child_fd in ready:
output = []
try:
while True:
s = os.read(child_fd, 1)
# EOF or EOL
if not s or s == "\n":
break
# don't store carriage returns (no universal line endings)
if not s == "\r":
output.append(s)
except OSError: # this signals EOF on some platforms
pass
if output.find("Enter password:") > -1:
os.write(child_fd, "password")