Python subprocess ist ein Modul, mit dem Sie externe Programme innerhalb des Codes ansteuern, ausführen und auswerten können. Die beiden wich­tigs­ten Funk­tio­nen dieses Tools sind run() und Popen().

Was ist Python subprocess?

Das Python-Modul subprocess gehört seit Version 2.4 fest zum Inventar der Pro­gram­mier­spra­che. Es handelt sich dabei um ein sehr um­fang­rei­ches und leis­tungs­star­kes Tool, das Sie nutzen können, um andere Programme oder Befehle innerhalb Ihres Codes aus­zu­füh­ren. Dabei ist es nicht nur möglich, Programme zu öffnen, sondern auch den Da­ten­fluss zu kon­trol­lie­ren und an­zu­pas­sen. Python subprocess bietet zahl­rei­che Methoden und Funk­tio­nen, von denen wir uns die wich­tigs­ten in diesem Artikel anschauen und anhand prak­ti­scher Beispiele erklären.

Managed Nextcloud by IONOS Cloud
Team­ar­beit in der eigenen Cloud
  • Voll­stän­di­ge Da­ten­sou­ve­rä­ni­tät in deutschen Re­chen­zen­tren
  • Managed Service ohne Ad­mi­nis­tra­ti­ons­auf­wand
  • File-Sharing, Do­ku­men­ten­be­ar­bei­tung & Kom­mu­ni­ka­ti­on

subprocess: Funk­ti­ons­wei­se mit run()

Vorher ist es al­ler­dings sinnvoll, einen Blick auf den Aufbau und die grund­sätz­li­che Funk­ti­ons­wei­se von Python subprocess zu werfen. Das Modul wird verwendet, um Un­ter­pro­zes­se aus­zu­füh­ren. Python funk­tio­niert dabei in der Eltern-Kind-Hier­ar­chie als über­ge­ord­ne­ter Part (Parent Process), der einen un­ter­ge­ord­ne­ten Prozess erstellt. Die Funktion, die innerhalb des Moduls am häu­figs­ten verwendet wird, ist run(). Diese erlaubt es Ihnen, einen Prozess über Python zu starten und beginnt weitere Schritte erst, wenn dieser voll­stän­dig durch­ge­führt wurde.

Beispiel für die Funk­ti­ons­wei­se von Python subprocess mit run()

Diese Funktion nutzen wir nun auch für unser erstes kleines Beispiel, mit dem wir die Funk­ti­ons­wei­se von Python subprocess ver­deut­li­chen können. Dafür im­por­tie­ren wir zunächst die Module subprocess und sys und führen dann eine einfache Auf­for­de­rung aus. Der ent­spre­chen­de Code sieht so aus:

import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "print('hallo')"])
python

Die Ausgabe ist dann diese:

hallo
python
  • subprocess.run: Dies ist die ei­gent­li­che Funktion. Sie erhält eine Liste mit Zei­chen­fol­gen, die den Befehl enthalten, der aus­ge­führt werden soll. run() führt dann ein neues Python-Programm aus.
  • sys.executable: Bei sys.executable handelt es sich um den absoluten Pfad, der zur Python-Datei führt, mit der Sie Ihr Programm ur­sprüng­lich auf­ge­ru­fen haben. Ein solcher Pfad könnte bei­spiel­haft so aussehen /local/nutzer/bin/beispiel.
  • -c: -c ist eine Be­fehls­zei­len­op­ti­on mit der die genannte Zei­chen­fol­ge zur Aus­füh­rung übergeben wird. Für unser Beispiel ist dies ein Programm, das das Wort „hallo“ ausgibt.

Python subprocess mit einem Skript ausführen

Um zu testen, wie Sie das Modul für ein eigens an­ge­fer­tig­tes Skript verwenden, können Sie das folgende Beispiel aus­pro­bie­ren. Dafür erstellen Sie zunächst ein einfaches Skript im .py-Format und speichern es als „bei­spiel­skript.py“:

print("Heute ist das Wetter gut")
python

Um diese Datei nun mit Python subprocess aus­zu­füh­ren, nutzen Sie den folgenden Code:

import subprocess
result = subprocess.run(["python", "beispielskript.py"], capture_output=True, text=True)
print(result.stdout)
python

Die ent­spre­chen­de Ausgabe wird dann so aussehen:

Heute ist das Wetter gut
python

Externe Programme öffnen

Grund­sätz­lich ist es mit Python subprocess und der Funktion run() möglich, ein be­lie­bi­ges Programm zu öffnen. Die einzige Vor­aus­set­zung dafür ist, dass Sie den genauen Namen oder den Pfad kennen, unter dem dieses Programm auf Ihrem System zu finden ist. Im folgenden Code öffnen wir bei­spiels­wei­se Notepad:

import subprocess
subprocess.run(["notepad"])
python

CompletedProcess und Erfassung externer Ausgaben

Nach diesen einfachen Bei­spie­len befassen wir uns nun mit der Erfassung einer externen Ausgabe. Dabei führen Sie ein externes Programm mit Python subprocess wie oben aus, lassen sich al­ler­dings ein so­ge­nann­tes CompletedProcess-Objekt zu­rück­ge­ben. Die dafür not­wen­di­gen An­pas­sun­gen haben wir weiter oben in einem Beispiel schon einmal kurz eingebaut, nun gehen wir näher darauf ein. Unser Aus­gangs­punkt ist wieder unser erster Code. Diesen passen wie nun aber an:

import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "print('hallo')"], capture_output=True, text=True)
print("Die Standardausgabe lautet:", result.stdout)
print("Dies ist der Standardfehler:", result.stderr)
python

Erneut weisen wir damit das System an, die Zei­chen­fol­ge „hallo“ aus­zu­ge­ben. Dies erfolgt in einem un­ter­ge­ord­ne­ten Prozess. Neu sind al­ler­dings die beiden Schlüs­sel­wort­ar­gu­men­te capture_output=True und text=True, die wir ebenfalls an run() übergeben. Wird die Anweisung aus­ge­führt und gibt es keine Fehler, erhalten Sie ein CompletedProcess-Objekt mit einer Bindung an result. Das Objekt enthält In­for­ma­tio­nen zum Exit-Code des Programms, das Sie ausführen lassen möchten, und gibt diese an result.stdout und result.stderr weiter. stdout be­zeich­net die Stan­dard­aus­ga­be, stderr mögliche Stan­dard­feh­ler. text=True nutzen wir dazu, um die Ausgabe als Zei­chen­fol­ge zu drucken. Da kein Stan­dard­feh­ler zu erwarten ist, lautet unser Ergebnis wie folgt:

Die Standardausgabe lautet: hallo
Dies ist der Standardfehler:
python

Um die Funk­ti­ons­wei­se besser zu ver­an­schau­li­chen, erstellen wir das nächste Beispiel so, dass stderr dieses Mal nicht leer bleibt. Der ent­spre­chen­de Code ist dieser:

import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "raise ValueError('fehler')"], capture_output=True, text=True)
print("Die Standardausgabe lautet:", result.stdout)
print("Dies ist der Standardfehler:", result.stderr)
python

Während die Stan­dard­aus­ga­be dieses Mal leer bleibt, gibt es für stderr nun eine Ausgabe:

Die Standardausgabe lautet:
Dies ist der Standardfehler: Traceback (most recent call last):
	File "<string>", line 1, in <module>
ValueError: fehler
python

Aus­füh­rung aus einer Funktion

Auch wenn Sie einen Befehl direkt in den Code einbauen möchten, bietet Ihnen Python subprocess diese Option. Der Code könnte in diesem Fall aussehen wie in diesem Beispiel:

import subprocess
result = subprocess.run(["C:/Users/name/anaconda3/python", "-c", "print('Diese Ausgabe wurde direkt aus einer Funktion übernommen')"], capture_output=True, text=True, shell=True)
print("Die Standardausgabe lautet:", result.stdout)
python

Unsere Ausgabe sieht dann so aus:

Die Standardausgabe lautet: Diese Ausgabe wurde direkt aus einer Funktion übernommen
python

Prozesse anhalten oder beenden

Ein weiterer sehr nütz­li­cher Ver­wen­dungs­zweck von Python subprocess wird durch das Zu­sam­men­spiel von run() mit dem timeout-Argument erreicht. Es er­mög­licht Ihnen, ein externes Programm an­zu­hal­ten, sofern seine Aus­füh­rung zu lange dauert. Dafür verwenden Sie die Funktion time.sleep. Der passende Code ist dieser:

import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "import time; time.sleep(3)"], timeout=1)
python

Der un­ter­ge­ord­ne­te Prozess nutzt time.sleep, um für drei Sekunden aus­zu­set­zen. Da Sie das System al­ler­dings über timeout=1 an­ge­wie­sen haben, nach einer Sekunde ein Timeout aus­zu­lö­sen, ist das Ergebnis eine TimeoutExpired-Ausnahme.

Python subprocess mit Popen()

Auch wenn run() die Funktion von Python subprocess ist, die am häu­figs­ten genutzt wird, gibt es noch andere wichtige Klassen, die sehr nützlich sein können. Dazu gehört auch Popen(). Diese Klasse ist quasi der Unterbau von Python subprocess und in der Anwendung etwas komplexer als run(). Dafür erhalten Sie über Popen() al­ler­dings mehr Kontrolle über die Aus­füh­rung und können mit dem Input und Output in­ter­agie­ren. Die Klasse verdankt ihren Namen einem UNIX-Befehl und steht für „pipe open“.

Beinahe alle Argumente, die Sie mit run() nutzen können, sind auch für Popen() zu­ge­las­sen. Im Gegensatz zu run() wartet diese Funktion al­ler­dings nicht bis ein Prozess ab­ge­schlos­sen ist, sondern startet parallel einen zweiten. Die Funk­ti­ons­wei­se können wir mit einem einfachen Beispiel ver­deut­li­chen:

import subprocess
from time import sleep
def poll_and_read(process):
    print(f"Dies ist die Ausgabe nach poll(): {process.poll()}")
    print(f"Dies ist die Standardausgabe: {process.stdout.read().decode('utf-8')}")
process = subprocess.Popen(["python", "timer.py", "3"], stdout=subprocess.PIPE)
poll_and_read(process)
sleep(2)
poll_and_read(process)
sleep(2)
poll_and_read(process)
process.wait()
print(f"Exit-Code des Prozesses: {process.returncode}")
python

Hierbei nutzen wir die Methode .poll(), um zu über­prü­fen, ob der Prozess noch läuft oder bereits ab­ge­schlos­sen ist. Solange er noch läuft, wird der Wert „none“ aus­ge­ge­ben. Danach gibt die Methode den Exit-Code aus. Mit .read() sollen alle Bytes aus­ge­le­sen werden, die sich bisher unter .stdout befinden. Wenn Sie den Code ausführen, werden Sie zuerst den Wert „None“ erhalten und danach den Wert, der bisher in stdout enthalten ist. Dies geht so lange, bis der Prozess durch­lau­fen wurde. Dann erhält poll() den Wert „0“.

Tipp

Apps und Websites direkt mit GitHub deployen: Bei Deploy Now von IONOS pro­fi­tie­ren Sie von einem schnel­le­ren Setup, op­ti­mier­ten Workflows und einer her­vor­ra­gen­den Ska­lier­bar­keit. Finden Sie den passenden Tarif für Ihre Zwecke!

Zum Hauptmenü