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?

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.


Ü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

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()

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.


4

Was Sie suchen, ist die waitMethode.


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")

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.