Die Antwort auf diese Frage hängt von der von Ihnen verwendeten Python-Version ab. Der einfachste Ansatz ist die Verwendung der subprocess.check_outputFunktion:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_outputführt ein einzelnes Programm aus, das nur Argumente als Eingabe verwendet. 1 Das Ergebnis wird genau so zurückgegeben, wie es gedruckt wurde stdout. Wenn Sie Eingaben schreiben müssen, fahren Sie stdinmit den Abschnitten runoder fort Popen. Wenn Sie komplexe Shell-Befehle ausführen möchten, lesen Sie den Hinweis am shell=TrueEnde dieser Antwort.
Die check_outputFunktion funktioniert auf fast allen Versionen von Python, die noch weit verbreitet sind (2.7+). 2 Für neuere Versionen ist dies jedoch nicht mehr der empfohlene Ansatz.
Moderne Versionen von Python (3.5 oder höher): run
Wenn Sie Python 3.5 oder höher verwenden und keine Abwärtskompatibilität benötigen , wird die neue runFunktion empfohlen. Es bietet eine sehr allgemeine API auf hoher Ebene für das subprocessModul. Übergeben Sie das subprocess.PIPEFlag an das stdoutSchlüsselwortargument, um die Ausgabe eines Programms zu erfassen . Greifen Sie dann auf das stdoutAttribut des zurückgegebenen CompletedProcessObjekts zu:
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Der Rückgabewert ist ein bytesObjekt. Wenn Sie also eine richtige Zeichenfolge wünschen, müssen Sie decodediese verwenden. Angenommen, der aufgerufene Prozess gibt eine UTF-8-codierte Zeichenfolge zurück:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Dies kann alles zu einem Einzeiler komprimiert werden:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Wenn Sie Eingaben an den Prozess übergeben möchten stdin, übergeben Sie ein bytesObjekt an das inputSchlüsselwortargument:
>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
Sie können Fehler erfassen, indem Sie stderr=subprocess.PIPE(Capture to result.stderr) oder stderr=subprocess.STDOUT(Capture to result.stdoutzusammen mit der regulären Ausgabe) übergeben. Wenn die Sicherheit keine shell=TrueRolle spielt , können Sie auch komplexere Shell-Befehle ausführen, indem Sie wie in den folgenden Hinweisen beschrieben übergeben.
Dies erhöht die Komplexität im Vergleich zur alten Vorgehensweise. Aber ich denke, es lohnt sich: Jetzt können Sie fast alles tun, was Sie brauchen, um die runFunktion alleine zu nutzen.
Ältere Versionen von Python (2.7-3.4): check_output
Wenn Sie eine ältere Version von Python verwenden oder eine bescheidene Abwärtskompatibilität benötigen, können Sie die check_outputFunktion wahrscheinlich wie oben kurz beschrieben verwenden. Es ist seit Python 2.7 verfügbar.
subprocess.check_output(*popenargs, **kwargs)
Es akzeptiert dieselben Argumente wie Popen(siehe unten) und gibt eine Zeichenfolge zurück, die die Ausgabe des Programms enthält. Der Anfang dieser Antwort enthält ein detaillierteres Verwendungsbeispiel. In Python 3.5 und höher check_outputentspricht dies der Ausführung runmit check=Trueund stdout=PIPEund der Rückgabe nur des stdoutAttributs.
Sie können übergeben, stderr=subprocess.STDOUTum sicherzustellen, dass Fehlermeldungen in der zurückgegebenen Ausgabe enthalten sind. In einigen Versionen von Python kann das Übergeben stderr=subprocess.PIPEan check_outputjedoch Deadlocks verursachen . Wenn die Sicherheit keine shell=TrueRolle spielt , können Sie auch komplexere Shell-Befehle ausführen, indem Sie wie in den folgenden Hinweisen beschrieben übergeben.
Wenn Sie stderrEingaben an den Prozess weiterleiten oder an diesen übergeben müssen, check_outputist dies nicht der Aufgabe gewachsen. Siehe die folgenden PopenBeispiele in diesem Fall.
Komplexe Anwendungen und Legacy-Versionen von Python (2.6 und niedriger): Popen
Wenn Sie eine umfassende Abwärtskompatibilität benötigen oder komplexere Funktionen als check_outputdie bereitgestellten benötigen , müssen Sie direkt mit PopenObjekten arbeiten, die die Low-Level-API für Unterprozesse kapseln.
Der PopenKonstruktor akzeptiert entweder einen einzelnen Befehl ohne Argumente oder eine Liste mit einem Befehl als erstem Element, gefolgt von einer beliebigen Anzahl von Argumenten, die jeweils als separates Element in der Liste aufgeführt sind. shlex.splitkann helfen, Zeichenfolgen in entsprechend formatierte Listen zu analysieren. PopenObjekte akzeptieren auch eine Vielzahl unterschiedlicher Argumente für die Prozess-E / A-Verwaltung und die Konfiguration auf niedriger Ebene.
Das Senden und Erfassen von Ausgaben communicateist fast immer die bevorzugte Methode. Wie in:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
Oder
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
Wenn Sie festlegen stdin=PIPE, communicatekönnen Sie auch Daten an den Prozess übergeben über stdin:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
Hinweis Aaron Hall Antwort , die das auf einigen Systemen gibt, können Sie festlegen müssen stdout, stderrund stdinalle PIPE(oder DEVNULL) zu erhalten , communicateüberhaupt zu arbeiten.
In einigen seltenen Fällen benötigen Sie möglicherweise eine komplexe Ausgabeerfassung in Echtzeit. Die Antwort von Vartec schlägt einen Weg nach vorne vor, aber andere Methoden als diese communicateneigen zu Deadlocks, wenn sie nicht sorgfältig angewendet werden.
Wie bei allen oben genannten Funktionen können Sie komplexere Shell-Befehle ausführen, wenn die Sicherheit keine Rolle spielt shell=True.
Anmerkungen
1. Shell-Befehle ausführen: das shell=TrueArgument
Normalerweise wird jeder Anruf run, check_outputoder der PopenKonstruktor führt ein einziges Programm . Das bedeutet, dass es keine ausgefallenen Pfeifen im Bash-Stil gibt. Wenn Sie komplexe Shell-Befehle ausführen möchten, können Sie übergeben shell=True, was alle drei Funktionen unterstützen.
Dies wirft jedoch Sicherheitsbedenken auf . Wenn Sie mehr als nur Light Scripting ausführen, ist es möglicherweise besser, jeden Prozess einzeln aufzurufen und die Ausgabe von jedem als Eingabe an die nächste über zu übergeben
run(cmd, [stdout=etc...], input=other_output)
Oder
Popen(cmd, [stdout=etc...]).communicate(other_output)
Die Versuchung, Rohre direkt anzuschließen, ist groß; widerstehen. Andernfalls werden Sie wahrscheinlich Deadlocks sehen oder Hacky Dinge wie zu tun dies .
2. Unicode-Überlegungen
check_outputGibt eine Zeichenfolge in Python 2 zurück, aber ein bytesObjekt in Python 3. Es lohnt sich, sich einen Moment Zeit zu nehmen , um etwas über Unicode zu lernen, wenn Sie dies noch nicht getan haben.