use*_*550 7 python subprocess python-3.3
我注意到两种不同的行为,两种方法应该产生相同的结果.
目标 - 使用子进程模块执行外部程序,发送一些数据并读取结果.
外部程序是PLINK,平台是WindowsXP,Python版本3.3.
主要想法 -
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()
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.
现在,我想能够做一个循环(在每次写入子进程的stdin之后),等待直到子进程的stdout的EOF,打印它,然后是另一个stdin命令,依此类推.
所以我首先尝试了之前关于相同主题的讨论产生(从subprocess命令实时输出,逐行读取子进程stdout,python,subprocess:从子进程读取输出).
并且它没有工作(它永远挂起),因为PLINK进程保持活着,直到我自己杀死它,因此没有使用等待子进程的stdout到达EOF或在stdout为真时进行循环,因为它在我杀了它之前一直都是真的.
所以我每次写stdin时都决定从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()
Run Code Online (Sandbox Code Playgroud)
但readline()据我所知,第一个额外的东西永远挂起,原因与我提到的相同.第一个额外的东西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()
Run Code Online (Sandbox Code Playgroud)
我试过这个,因为根据文档communicate(),函数等到进程结束,然后结束.此外,它从stdout读取直到EOF.(与写入和读取stdout和stdin相同)
但是communicate()完成并且没有挂起,与前面的代码块相反.
我在这里错过了什么?为什么在使用communicate()PLINK时会结束,但在使用readline()它时却没有?
您的程序没有communicate()死锁,因为两个进程都在等待对方写一些东西,然后再自己写更多东西。
communicate()在您的示例中不会死锁,因为它a.stdin.close()会像命令一样关闭流。这会向您的子进程发送一个 EOF,让它知道没有更多输入,因此它可以关闭自己,进而关闭其输出,因此a.stdout.read()最终返回一个 EOF(空字符串)。
您的主进程不会从您的子进程收到任何特殊信号,让您知道它已完成从一个命令写入结果,但已准备好接收另一个命令。
这意味着要像您尝试的那样与一个子进程来回通信,您必须读取子进程发送的确切行数。就像你看到的,如果你试图阅读太多的行,你就会陷入僵局。您或许可以使用您所知道的信息(例如您发送的命令以及您目前看到的输出)来准确计算出要读取的行数。