Python-Popen-Befehl. Warten Sie, bis der Befehl beendet ist

79

Ich habe ein Skript, in dem ich mit popen einen Shell-Befehl starte. Das Problem ist, dass das Skript nicht wartet, bis der Befehl popen beendet ist, und sofort fortfährt.

om_points = os.popen(command, "w")
.....

Wie kann ich meinem Python-Skript mitteilen, dass es warten soll, bis der Shell-Befehl beendet ist?

michele
quelle

Antworten:

110

Je nachdem, wie Sie Ihr Skript bearbeiten möchten, haben Sie zwei Möglichkeiten. Wenn Sie möchten, dass die Befehle blockieren und während der Ausführung nichts tun, können Sie sie einfach verwenden subprocess.call.

#start and block until done
subprocess.call([data["om_points"], ">", diz['d']+"/points.xml"])

Wenn Sie Dinge tun möchten, während sie ausgeführt werden, oder Dinge einspeisen möchten stdin, können Sie sie communicatenach dem popenAufruf verwenden.

#start and process things, then wait
p = subprocess.Popen([data["om_points"], ">", diz['d']+"/points.xml"])
print "Happens while running"
p.communicate() #now wait plus that you can send commands to process

Wie in der Dokumentation angegeben, waitkann ein Deadlock auftreten, daher ist eine Kommunikation ratsam.

unholysampler
quelle
Überprüfen Sie die Dokumentation auf out subprocess.call
thornomad
Während Unterprozesse in vielen Antworten bevorzugt werden, können Speicherplatz und Kontingent innerhalb des Befehls nicht sehr gut verarbeitet werden. Die obige Antwort löst die os.popen-Frage nicht direkt.
Chang
Der Unterprozess kann bis zu 2x langsamer sein als das Betriebssystem
MonsieurBeilto
subprocess.run()wurde in Python 3.5 hinzugefügt und ist "Der empfohlene Ansatz zum Aufrufen von
Unterprozessen
29

Sie können dies verwenden subprocess, um dies zu erreichen.

import subprocess

#This command could have multiple commands separated by a new line \n
some_command = "export PATH=$PATH://server.sample.mo/app/bin \n customupload abc.txt"

p = subprocess.Popen(some_command, stdout=subprocess.PIPE, shell=True)

(output, err) = p.communicate()  

#This makes the wait possible
p_status = p.wait()

#This will give you the output of the command being executed
print "Command output: " + output
Prüfstein
quelle
Der Unterprozess kann bis zu 2x langsamer sein als das Betriebssystem
MonsieurBeilto
12

Erzwingen Sie popen, nicht fortzufahren, bis alle Ausgaben gelesen wurden.

os.popen(command).read()
Alberto
quelle
2
Ich bin kein Python-Experte, aber dies scheint die einfachste Lösung zu sein, die die wenigsten Änderungen am Originalcode vornimmt. Gibt es einen Grund, warum dies keine gute Lösung wäre?
jdmcnair
6

Lassen Sie den Befehl, den Sie übergeben möchten, sein

os.system('x')

dann verdeckst du es zu einer Aussage

t = os.system('x')

Jetzt wartet die Python auf die Ausgabe über die Befehlszeile, damit sie der Variablen zugewiesen werden kann t.

Chidhambararajan NRM
quelle
4

Was Sie suchen, ist die waitMethode.

Olivier Verdier
quelle
Aber wenn ich Folgendes eingebe: om_points = os.popen (data ["om_points"] + ">" + diz ['d'] + "/ points.xml", "w"). Wait () Ich erhalte diesen Fehler: Traceback (letzter Aufruf zuletzt): Datei "./model_job.py", Zeile 77, in <module> om_points = os.popen (data ["om_points"] + ">" + diz ['d'] + "/ points .xml "," w "). wait () AttributeError: 'Datei'-Objekt hat kein Attribut' wait 'Was ist das Problem? Danke noch einmal.
michele
12
Sie haben nicht auf den von mir angegebenen Link geklickt. waitist eine Methode der subprocessKlasse.
Olivier Verdier
1
Warten kann Deadlock, wenn der Prozess in stdout schreibt und niemand es liest
ansgri
Der Unterprozess kann bis zu 2x langsamer sein als das Betriebssystem
MonsieurBeilto
2

wait () funktioniert gut für mich. Die Teilprozesse p1, p2 und p3 werden gleichzeitig ausgeführt. Daher sind alle Prozesse nach 3 Sekunden abgeschlossen.

import subprocess

processes = []

p1 = subprocess.Popen("sleep 3", stdout=subprocess.PIPE, shell=True)
p2 = subprocess.Popen("sleep 3", stdout=subprocess.PIPE, shell=True)
p3 = subprocess.Popen("sleep 3", stdout=subprocess.PIPE, shell=True)

processes.append(p1)
processes.append(p2)
processes.append(p3)

for p in processes:
    if p.wait() != 0:
        print("There was an error")

print("all processed finished")
simibac
quelle
Der Unterprozess kann bis zu 2x langsamer sein als das Betriebssystem
MonsieurBeilto
0

Ich denke, process.communicate () wäre für eine Ausgabe mit geringer Größe geeignet. Für eine größere Leistung wäre dies nicht der beste Ansatz.

Barsha Lamichhane
quelle