Я заметил два разных поведения с двумя подходами, которые должны были привести к одному и тому же результату.subprocess popen.communicate() vs. stdin.write() и stdout.read()
Цель - выполнить внешнюю программу с использованием модуля подпроцесса, отправить некоторые данные и прочитать результаты.
Внешняя программа PLINK, платформа WindowsXP, версия 3.3 для Python.
Основной idea-
execution=["C:\\Pr..\\...\\plink.exe", "-l", username, "-pw", "***", IP]
a=subprocess.Popen(execution, bufsize=0, stdout=PIPE, stdin=PIPE, stderr=STDOUT, shell=False)
con=a.stdout.readline()
if (con.decode("utf-8").count("FATAL ERROR: Network error: Connection timed out")==0):
a.stdin.write(b"con rout 1\n")
print(a.stdout.readline().decode("utf-8"))
a.stdin.write(b"infodf\n")
print(a.stdout.readline().decode("utf-8"))
else:
print("ERROR")
a.kill()
До сих пор так хорошо.
Теперь я хочу иметь возможность делать цикл (после каждой записи на stdin подпроцесса), который ждет до EOF в стандартном дескрипторе sub, печатает его, затем другую команду stdin и т. Д.
Итак, я сначала попробовал, какие предыдущие обсуждения о том же уроке темы (live output from subprocess command, read subprocess stdout line by line, python, subprocess: reading output from subprocess).
И он не работал (он вечно вечно), потому что процесс PLINK остается в живых до тех пор, пока я его не уничтожу, поэтому нет необходимости ждать, пока stdout вспомогательного процесса достигнет EOF или сделайте цикл while stdout истинно, потому что это всегда будет правдой, пока я не убью его.
Так что я решил читать стандартный вывод в два раза каждый раз, когда я пишу на стандартный ввод (хороший прийти для меня) -
execution=["C:\\Pr..\\...\\plink.exe", "-l", username, "-pw", "***", IP]
a=subprocess.Popen(execution, bufsize=0, stdout=PIPE, stdin=PIPE, stderr=STDOUT, shell=False)
con=a.stdout.readline()
if (con.decode("utf-8").count("FATAL ERROR: Network error: Connection timed out")==0):
a.stdin.write(b"con rout 1\n")
print(a.stdout.readline().decode("utf-8"))
print(a.stdout.readline().decode("utf-8")) //the extra line [1]
a.stdin.write(b"infodf\n")
print(a.stdout.readline().decode("utf-8"))
print(a.stdout.readline().decode("utf-8")) //the extra line [2]
else:
print("ERROR")
a.kill()
Но первый дополнительный readline()
вешает навсегда, насколько я понимаю, для того же причина, о которой я упоминал. Первый дополнительный readline()
ждет навсегда для вывода, потому что единственный выход уже был прочитан в первом , а поскольку PLINK жив, функция просто «сидит» там и ждет выхода новой выходной линии.
Так что я попробовал этот код, ожидая того же повесить, потому что Plink никогда не умирает, пока я не убить это-
execution=["C:\\Pr..\\...\\plink.exe", "-l", username, "-pw", "***", IP]
a=subprocess.Popen(execution, bufsize=0, stdout=PIPE, stdin=PIPE, stderr=STDOUT, shell=False)
con=a.stdout.readline()
if (con.decode("utf-8").count("FATAL ERROR: Network error: Connection timed out")==0):
a.stdin.write(b"con rout 1\n")
print(a.stdout.readline().decode("utf-8"))
a.stdin.write(b"infodf\n")
print(a.stdout.readline().decode("utf-8"))
print(a.communicate()[0].decode("utf-8")) //Popen.communicate() function
else:
print("ERROR")
a.kill()
Я пробовал, потому что в соответствии с документацией communicate()
, функция ожидания до процесса закончился, а затем он заканчивается. Кроме того, он считывает с stdout до EOF. (так же, как запись и чтение stdout и stdin)
Но communicate()
заканчивается и не висит, в отличие от предыдущего кода.
Что мне здесь не хватает? почему при использовании communicate()
PLINK заканчивается, но при использовании readline()
это не так?
Извините, но это не ответ на мой вопрос. Я знаю этот факт :) – user2162550