Python-Unterprozess liest Stdout während der Ausführung
-
Python-Unterprozess liest
stdout
während der Ausführung -
Ansatz 1: Verwenden Sie
check_call
, umstdout
einessubprocess
zu lesen, während er in Python ausgeführt wird -
Ansatz 2: Abfragen des Prozesses zum Lesen von
stdout
einessubprocess
während der Ausführung in Python
Das Hauptziel dieses Artikels ist es zu zeigen, wie man die stdout
eines subprocess
liest, der in Python ausgeführt wird.
Python-Unterprozess liest stdout
während der Ausführung
Wie bei vielen anderen eingebauten Modulen ist auch Subprocess
ein eingebautes Modul, das bei einer “normalen” Python-Installation vorinstalliert ist.
Es wird hauptsächlich verwendet, wenn Sie Aufgaben, Prozesse und Programme in einem neuen Prozess ausführen, einen bestimmten Satz von Aufgaben ausführen und das Ergebnis zurückgeben möchten.
Einer der vielen Gründe für die breite Verwendung ist, dass es die Ausführung externer Programme und ausführbarer Dateien direkt aus dem Programm als separaten Prozess ermöglicht.
Beim Ausführen eines Programms mit der Bibliothek Subprocess
kann es erforderlich sein, dass die Ausgabe dieses externen Programms in Echtzeit angezeigt wird. Dies kann aus vielen Gründen erforderlich sein, z. B. wenn ein Programm in Echtzeit läuft und nach kurzer Zeit von Berechnungen abhängt.
Betrachten Sie das folgende Programm:
import subprocess
def execute(command):
process = subprocess.Popen(
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
output = process.communicate()[0]
exitCode = process.returncode
if exitCode == 0:
return output
else:
raise Exception(command, exitCode, output)
if __name__ == "__main__":
print(execute("cd C:\\ && C: && tree").decode("unicode_escape"))
Ausgang:
Folder PATH listing
Volume serial number is 0213-B7F2
C:.
+---DRIVERS
¦ +---bluetooth
¦ +---U1BLT07AVVASDSAP
¦ +---Custom
¦ ¦ +---EULA
¦ +---Win64
¦ +---LD
¦ +---svcpack
+---flutter
¦ +---.git
¦ ¦ +---hooks
¦ ¦ +---info
¦ ¦ +---logs
¦ ¦ ¦ +---refs
¦ ¦ ¦ +---heads
¦ ¦ ¦ +---remotes
¦ ¦ ¦ +---origin
¦ ¦ +---objects
¦ ¦ ¦ +---info
¦ ¦ ¦ +---pack
¦ ¦ +---refs
¦ ¦ +---heads
¦ ¦ +---remotes
¦ ¦ ¦ +---origin
¦ ¦ +---tags
¦ +---.github
¦ ¦ +---ISSUE_TEMPLATE
¦ ¦ +---workflows
¦ +---.idea
¦ ¦ +---runConfigurations
...
Wir können die Ausgabe im Programm sehen, aber nicht in Echtzeit. Die Ausgabe wird erst angezeigt, nachdem der gesamte Befehl (in unserem Fall Baum
) ausgeführt wurde.
Die Ausgabe zeigt nichts, bis das Programm (oder der Befehl) in einem separaten Prozess mit dem Befehl Subprocess
ausgeführt wird.
Da es in unserem Fall erforderlich ist, dass wir die Ausgabe in Echtzeit erhalten, müssen wir eine andere Lösung erstellen, die die Ausgabe des Programms zeigt, wie sie in die stdout
geschrieben wird.
Die Lösung kann auf mehrere Arten angegangen werden, von denen einige unten erwähnt werden.
Ansatz 1: Verwenden Sie check_call
, um stdout
eines subprocess
zu lesen, während er in Python ausgeführt wird
Betrachten Sie den folgenden Code:
import subprocess
import sys
def execute(command):
subprocess.check_call(
command, shell=True, stdout=sys.stdout, stderr=subprocess.STDOUT
)
if __name__ == "__main__":
print(execute("cd C:\\ && C: && tree").decode("unicode_escape"))
Ausgang:
Folder PATH listing
Volume serial number is 0213-B7F2
C:.
├───DRIVERS
│ └───bluetooth
│ └───U1BLT0720US14CMP
│ ├───Custom
│ │ └───EULA
│ └───Win64
│ ├───LD
│ └───svcpack
├───flutter
│ ├───.git
│ │ ├───hooks
│ │ ├───info
│ │ ├───logs
│ │ │ └───refs
│ │ │ ├───heads
│ │ │ └───remotes
│ │ │ └───origin
│ │ ├───objects
│ │ │ ├───info
│ │ │ └───pack
│ │ └───refs
│ │ ├───heads
│ │ ├───remotes
│ │ │ └───origin
│ │ └───tags
│ ├───.github
│ │ ├───ISSUE_TEMPLATE
│ │ └───workflows
│ ├───.idea
│ │ └───runConfigurations
│ ├───.pub-cache
│ │ ├───hosted
│ │ │ └───pub.dartlang.org
│ │ │ ├───.cache
...
Wenn die Hauptanforderung darin besteht, die Ausgabe des Programms in Echtzeit zu drucken, kann dies mit check_call
erreicht werden. Diese einfache, saubere und elegante Lösung ist prägnant und “einfach perfekt” für sehr einfache Programme, z. B. wenn nur die Ausgabe gedruckt werden soll.
Der check_call
unterstützt auch die Übergabe von Parametern. Wenn Ihr Programm also Argumente benötigt, um zu funktionieren, können diese einfach und problemlos an die Funktion übergeben werden. Diese Methode wartet auf den Abschluss des Programms.
Basierend auf dem Abschluss des Programms kehrt das Verfahren zurück; andernfalls wird eine CalledProcessError
-Ausnahme ausgelöst. Der CalledProcessError
enthält den Rückgabecode des Fehlers, auf den über das Attribut returncode
zugegriffen werden kann.
Im oben erwähnten Code wird der Befehl
an die Methode check_call
übergeben, die den auszuführenden Befehl (bzw. das Programm) enthält.
Der Parameter shell
wurde auf true
gesetzt, um den Prozess mit einer Shell auszuführen, und die stdout
des Prozesses ist auf die stdout
unseres Programms gesetzt, sodass er direkt in unsere stdout
schreibt, und wir können Sehen Sie sich die Änderungen in unserem stdout
an.
Zuletzt wird stderr
auf stdout
des erzeugten Prozesses gesetzt.
Ansatz 2: Abfragen des Prozesses zum Lesen von stdout
eines subprocess
während der Ausführung in Python
Betrachten Sie den folgenden Code:
import subprocess
import sys
def execute(command):
process = subprocess.Popen(
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
# Poll process for new output until finished
while True:
nextline = process.stdout.readline().decode("unicode_escape")
if nextline == "" and process.poll() is not None:
break
sys.stdout.write(nextline)
sys.stdout.flush()
output = process.communicate()[0]
exitCode = process.returncode
if exitCode == 0:
return output
else:
raise Exception(command, exitCode, output)
if __name__ == "__main__":
print(execute("cd C:\\ && C: && tree").decode("unicode_escape"))
Ausgang:
...
¦ ¦ ¦ ¦ ¦ +---UuidUtil
¦ ¦ ¦ ¦ +---example
¦ ¦ ¦ ¦ +---lib
¦ ¦ ¦ ¦ +---test
¦ ¦ ¦ +---vector_math-2.1.2
¦ ¦ ¦ ¦ +---benchmark
¦ ¦ ¦ ¦ +---bin
¦ ¦ ¦ ¦ +---lib
¦ ¦ ¦ ¦ ¦ +---src
¦ ¦ ¦ ¦ ¦ +---vector_math
¦ ¦ ¦ ¦ ¦ ¦ +---third_party
¦ ¦ ¦ ¦ ¦ +---vector_math_64
¦ ¦ ¦ ¦ ¦ ¦ +---third_party
¦ ¦ ¦ ¦ ¦ +---vector_math_geometry
¦ ¦ ¦ ¦ ¦ ¦ +---filters
¦ ¦ ¦ ¦ ¦ ¦ +---generators
¦ ¦ ¦ ¦ ¦ +---vector_math_lists
¦ ¦ ¦ ¦ ¦ +---vector_math_operations
¦ ¦ ¦ ¦ +---test
¦ ¦ ¦ ¦ +---tool
¦ ¦ ¦ +---video_player-2.2.11
¦ ¦ ¦ ¦ +---android
¦ ¦ ¦ ¦ ¦ +---gradle
...
Um sicherzustellen, dass die Ausgabe des Programms, die mit dem Subprocess
erzeugt wurde, gedruckt wird, sobald sie in die stdout
geschrieben wird, müssen wir den Prozess für die Ausgabe abfragen und mit dem Lesen der letzten Zeile der stdout
der stdout
des Programms fortfahren.
In einer Endlos
-Schleife lesen wir die Ausgabe des gespawnten Prozesses mit readline()
weiter. Da die Ausgabe kodiert ist, müssen wir sie dekodieren (in unserem Fall utf-escape
), um angemessen dargestellt zu werden.
Dies kann mit der Methode decode
und Übergabe des entsprechenden Verschlüsselungsschemas erfolgen.
Sobald das Programm die Ausführung beendet hat, müssen wir auch die “Endlos”-Schleife verlassen. Wir können dies tun, indem wir zwei Dinge überprüfen:
- Die aktuelle
stdout
-Zeile ist leer. - Der Prozess wurde beendet oder starb.
Das geht ganz einfach, mit einem einfachen String-Vergleich für die erste Bedingung und der Methode poll()
, um zu prüfen, ob der Prozess beendet ist oder nicht. Ist das Programm beendet, gibt es den returncode
zurück; andernfalls wird None
zurückgegeben.
Ein einfacher Vergleich mit None
kann uns auch Aufschluss darüber geben, ob das Programm mit der Ausführung fertig ist oder nicht.
Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.
LinkedIn