Запись на stdin, а также правильная распечатка результатов

У меня есть команда ./rancli -c - Я вхожу в оболочку с этой документацией:

Запуск инструмента из оболочки Linux позволяет использовать дополнительные опции, в зависимости от параметров, заданных команде. Возможные варианты: следующим образом:

-h Отображает справку о команде

-c Вместо того, чтобы интерактивно вводить типизированные команды от пользователя, команды считываются из именованного файла, то есть в пакетном режиме. Когда все команды обрабатываются, сеанс CLI заканчивается автоматически.

-c - Как указано выше, но читает команду из Linux stdin. Это позволяет командам быть переданными в программу.

Я хочу преобразовать это в python. Если я использую второй вариант, все работает отлично, и он считывает команды из файла и отображает результаты на экране. Однако я хочу использовать третий вариант, который записывает в stdin. Я бы подумал, что эта строка будет запускать команду ./rancli -c - commandHere, но это не так. Что мне нужно сделать, это ввести ./rancli -c -, тогда я могу написать вручную для stdin на следующей строке, например, здесь я использую команду read hnb:

[[email protected]]# ./rancli -c -
read hnb
RAN> read hnb
               HNBId                           Location      RegUEs   ActUEs
  [email protected]                    n/c
  [email protected]                    n/c

Когда я ввожу это в оболочку, я получаю результат, напечатанный в порядке. Однако, когда я делаю это на своем питоне, я не верну мне вернувшиеся результаты. Вот что я пробовал:

    ran_opt_get_ap  = "read hnb\n"
    cmd_rancli = ["/jffs2/usbflash0/ran/rancli", "-c", "-"]
    proc = subprocess.Popen(cmd_rancli + [ran_opt_get_ap], stdout=subprocess.PIPE)    
    for line in iter(proc.stdout.readline, ''): 
        print line,
    proc.wait()

Итак, когда я передаю команду вроде этого, она явно не работает, как в оболочке, и игнорируется. Теперь два вопроса здесь. Как написать команду для stdin здесь, так как мне пришлось набирать следующую команду read hnb вручную? После того, как я запустил rancli -c -, я хочу, чтобы потом вводить команды после, я должен ввести его так же, как сейчас:

read hnb                                                                        
RAN> read hnb                   

Другая проблема заключается в том, что мой код не распечатывал полные результаты выше, но когда я печатаю следующую команду, я получаю остальную часть результатов и первую строку следующего результата и так далее с каждой командой, получая результаты после ввода следующей команды:

get ap                                                                          
               HNBId                           Location      RegUEs   ActUEs    
  [email protected]                    n/c                         
  [email protected]                    n/c                         
RAN> get ap 

Обновление: последние работы кода

cmd_rancli = ["/jffs2/usbflash0/ran/rancli", "-c", "-"]
ran_opt_get_ap = "read hnb"
proc = subprocess.Popen(cmd_rancli, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output = proc.communicate(ran_opt_get_ap)[0] 
print output

Ответ 1

Чтобы записать в подпроцесс 'stdin, установите его в PIPE:

from subprocess import Popen, PIPE

p = Popen(cmd_rancli, stdin=PIPE, stdout=PIPE)
output = p.communicate(ran_opt_get_ap)[0]

.communicate() записывает ran_opt_get_ap в подпроцесс 'stdin, читает весь вывод и ждет завершения дочернего процесса.

Вторая проблема связана с буферизацией (это имеет значение только в том случае, если вы не читаете сразу весь вывод). Чтобы исправить буферизацию:

  • вывода вашей программы, добавьте sys.stdout.flush() после печати
  • трубы на вашем конце, установите параметр Popen bufsize в ноль
  • подпроцесса, используйте pexpect, pty модули или stdbuf, unbuffer, script.