subprocess popen.kommunizieren() vs. stdin.write() und stdout.read()
Habe ich bemerkt, zwei verschiedene Verhaltensweisen, die mit beiden Ansätzen, sollten haben das gleiche Ergebnis zufolge.
Ziel - ausführen eines externen Programms über subprocess-Modul, senden Sie einige Daten und Lesen Sie die Ergebnisse.
Dem externen Programm PLINK, Plattform ist WindowsXP, die Python in der version 3.3.
Die Haupt-Idee-
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()
So weit So gut.
Nun, ich möchte in der Lage sein zu tun, eine Schleife (nach jedem schreiben in die sub-Prozess stdin) und wartet, bis EOF von der sub-Prozess stdout, drucken Sie es, dann in die andere stdin Befehl, und so weiter.
So versuchte ich zunächst, was die bisherigen Diskussionen über das gleiche Thema yield (live-Ausgabe von Teilprozess-Befehl, Lesen Teilprozess stdout zeilenweise, python-subprocess: Lesen-Ausgabe von Teilprozess) .
Und es hat nicht funktioniert (es hängt ewig), weil die PLINK-Prozess ist noch am Leben, bis ich es tötet mich, es ist also kein Einsatz zu warten, für die stdout von der sub-Prozess zu erreichen, EOF, oder eine Schleife, während stdout true ist, da es immer treu sein, bis ich es töten.
Also beschloss ich, zu Lesen von stdout zweimal jedes mal, wenn ich Schreibe stdin (gut genug für mich)-
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()
Aber das erste extra readline()
hängt für immer, soweit ich das verstanden habe, aus den gleichen Gründen, die ich erwähnt. Das erste extra readline()
wartet ewig für die Ausgabe, weil Sie die einzige Ausgabe war bereits zu Lesen, in der ersten readline()
, und da PLINK lebendig ist, wird die Funktion einfach "sitzen" dort und wartet auf einen neuen line-Ausgang zu bekommen.
So, ich habe versucht, diesen code, in der Erwartung, den gleichen hängen, da PLINK stirbt nie, bis ich es töten-
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()
Versuchte ich, denn laut der Dokumentation von communicate()
die Funktion warten, bis der Prozess endete, und dann ist es beendet. Auch, es liest von stdout bis EOF. (das gleiche wie das schreiben und Lesen von stdout und stdin)
Aber communicate()
beendet und nicht hängen, im Gegenteil zu den vorherigen code-block.
Was vermisse ich hier? warum bei der Verwendung von communicate()
die PLINK endet, aber bei der Verwendung von readline()
es nicht?
InformationsquelleAutor user2162550 | 2014-01-15
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihr Programm ohne
communicate()
deadlocks, da beide Prozesse warten gegenseitig auf, etwas zu schreiben, bevor Sie schreiben nichts mehr selbst.communicate()
nicht deadlock in deinem Beispiel, weil es den stream schließt, wie der Befehla.stdin.close()
würde. Dieser sendet ein EOF zu Ihrem Teilprozess, es wissen zu lassen, dass es nicht mehr input kommt, so kann es sich zu schließen, was wiederum schließt seine Ausgabe, soa.stdout.read()
schließlich liefert ein EOF-Zeichen (leer-string).Es gibt keine spezielle signal, die Ihren main-Prozess erhalten von Ihrem Teilprozess, Sie wissen zu lassen, dass es getan wird, schreiben Sie die Ergebnisse von einem Befehl, aber bereit ist, für einen anderen Befehl.
Dies bedeutet, dass die Kommunikation hin und her mit einem Teilprozess, wie Sie versuchen, Lesen Sie bitte die genaue Anzahl der Zeilen, die den Teilprozess sendet. Wie Sie sah, wenn Sie versuchen zu Lesen, zu viele Linien, man deadlock. Sie könnten in der Lage sein, um verwenden Sie, was Sie wissen, wie die Befehl, die Sie ihn geschickt, und die Ausgabe, die Sie bisher gesehen haben, um genau herauszufinden, wie viele Zeilen zu Lesen.
InformationsquelleAutor Dan Getz
Die Sache ist, dass bei der Verwendung von
subprocess.Popen
Ihren code nach wie vor gelesen werden, noch bevor der Prozess beendet ist. Versuchen Sie.wait()
zu Ihrem Popen-Aufruf (siehe Dokumentation),Dadurch wird sichergestellt, dass die Ausführung beendet, bevor irgendetwas anderes.
InformationsquelleAutor tchuncly
Können Sie nutzen, threads schreiben und Lesen zur gleichen Zeit, vor allem, wenn die Ausgabe muss nur ausgedruckt werden, um dem Benutzer:
InformationsquelleAutor Dan Getz