Je kunt de Python subprocess-module gebruiken om nieuwe processen te creëren, te koppelen aan hun invoer en uitvoer, en hun returncodes en/of uitvoer op te halen. In dit artikel bekijken we de basis van de subprocess-module, waaronder het uitvoeren van externe commando's, het omleiden van invoer en uitvoer, en het afhandelen van fouten. Of je nu een beginner bent of een ervaren Python-ontwikkelaar, deze tutorial geeft je de kennis die je nodig hebt om de subprocess-module effectief te gebruiken in je projecten.
Wat is Python Subprocess?
De Python subprocess-module is een hulpmiddel waarmee je andere programma's of commando's vanuit je Python-code kunt uitvoeren. Je kunt er nieuwe programma's mee openen, gegevens naartoe sturen en resultaten terugkrijgen.
De Python subprocess-module gebruiken is alsof je je computer commando's geeft met Python in plaats van ze direct in de commandoregel te typen. Deze module maakt het gemakkelijk om taken te automatiseren en andere programma's te integreren met je Python-code. Zo kun je met de subprocess-module een shell-commando zoals ls of ping uitvoeren en de uitvoer van dat commando in je Python-code gebruiken. Je kunt er ook andere Python-scripts of uitvoerbare bestanden mee starten, zoals .exe-bestanden op Windows.
Daarnaast kan de subprocess-module de invoer en uitvoer van het proces omleiden, wat betekent dat je kunt bepalen welke data naar het proces wordt gestuurd en welke data je ervan ontvangt.
Een van de nuttigste mogelijkheden van de subprocess-module is dat je de invoer, uitvoer en fouten (meestal op stderr) van het kindproces kunt afhandelen. Met check=True wordt een CalledProcessError opgegooid en kun je e.stdout/e.stderr inspecteren. Deze feature wordt gezien als een van de krachtigste aspecten van de module. Daardoor is het aanroepen van subprocessen krachtiger en veelzijdiger geworden. Je kunt bijvoorbeeld de uitvoer van het subprocess als variabele gebruiken in de rest van je Python-script.
Wanneer gebruik je Python Subprocess
Laten we bekijken wanneer je de Python subprocess-module gebruikt.
Systeemtaken automatiseren
De subprocess-module kan worden gebruikt om verschillende systeemtaken te automatiseren, zoals backups draaien, services starten en stoppen, en cronjobs plannen. Je kunt bijvoorbeeld met de subprocess-module het commando cp uitvoeren om een back-up van een bestand te maken of systemctl (modern Linux) of service (oudere systemen) gebruiken om services te starten en te stoppen. Je kunt met subprocess ook planningshulpmiddelen aanroepen (zoals cron op Linux of Taakplanner op Windows), maar het plannen zelf wordt door die tools gedaan, niet door subprocess.
Commandlinetools uitvoeren
De subprocess-module kan worden gebruikt om commandlinetools zoals grep, sed en awk uit te voeren en hun uitvoer in je Python-code te verwerken. Je kunt bijvoorbeeld met de subprocess-module het commando grep uitvoeren om naar een specifiek patroon in een bestand te zoeken en de uitvoer vervolgens in je Python-code verwerken. Dit is handig voor taken zoals loganalyse, gegevensverwerking en tekstmanipulatie.
Externe executables uitvoeren
De subprocess-module kan andere uitvoerbare bestanden starten, zoals .exe-bestanden op Windows, en hun gedrag aansturen. Je kunt bijvoorbeeld met de subprocess-module een executable draaien die een specifieke taak uitvoert en vervolgens de uitvoer daarvan in je eigen code gebruiken. Dit is handig voor beeldbewerking, data-analyse en machine learning-taken.
Scripts als achtergrondproces draaien
Je kunt de subprocess-module gebruiken om scripts als achtergrondprocessen te draaien zodat ze blijven lopen nadat het hoofdprogramma is afgesloten. Je kunt bijvoorbeeld met de subprocess-module een script draaien dat een specifieke taak uitvoert en het hoofdprogramma afsluiten zonder te wachten tot het script klaar is. Dit is handig voor monitoring, logging en dataverzameling.
Scripts met een niet-Python-interpreter draaien
De subprocess-module kan je helpen scripts te draaien die in andere talen zijn geschreven, zoals Perl, Ruby en Bash. Je kunt bijvoorbeeld met de subprocess-module een Perl-script uitvoeren dat een specifieke taak doet en vervolgens de uitvoer van dat script in je eigen code gebruiken. Dit is handig voor gegevensverwerking, tekstmanipulatie en systeembeheer.
Parallelle verwerking
De subprocess-module kan worden gebruikt om meerdere processen parallel te draaien, wat handig kan zijn voor taken zoals beeldverwerking, data-analyse en machine learning. Je kunt bijvoorbeeld met de subprocess-module meerdere instanties van hetzelfde script draaien, elk op een ander deel van de data, en de resultaten daarna combineren.
Voer de code uit deze tutorial online uit en pas 'm aan.
Code uitvoerenPython Subprocess-voorbeelden
Laten we nu enkele voorbeelden van Python subprocess bekijken.
python subprocess run
De methode subprocess.run() is een handige manier om een subprocess te draaien en te wachten tot het klaar is. Je kiest het commando om uit te voeren en kunt opties toevoegen zoals argumenten, omgevingsvariabelen en omleidingen van invoer/uitvoer. Zodra het subprocess is gestart, blokkeert de methode run() totdat het subprocess voltooid is en geeft een CompletedProcess-object terug met de returncode en uitvoer van het subprocess.
De methode subprocess.run() accepteert verschillende argumenten, waaronder:
-
args: Het uit te voeren commando en de argumenten, doorgegeven als een lijst met strings. -
capture_output: Als dit True is, worden standaarduitvoer en standaardfout opgevangen. -
text: Als dit True is, worden stdout en stderr als string geretourneerd, anders als bytes. -
check: een boolean die aangeeft of de returncode van het subprocess moet worden gecontroleerd; als check True is en de returncode is niet nul, dan wordt subprocessCalledProcessErroropgegooid. -
timeout: Een waarde in seconden die aangeeft hoelang gewacht wordt tot het subprocess klaar is voordat het afloopt. -
shell: Een boolean die aangeeft of het commando in een shell moet worden uitgevoerd. Dit betekent dat het commando als string wordt doorgegeven en dat shellspecifieke features zoals wildcardexpansie en variabele substitutie gebruikt kunnen worden.
De methode subprocess.run() retourneert ook een CompletedProcess-object met de volgende attributen:
-
args: Het commando en de argumenten die zijn uitgevoerd. -
returncode: De returncode van het subprocess. -
stdout: De standaarduitvoer van het subprocess (string als text=True, anders bytes). stderr: De standaardfout van het subprocess (string als text=True, anders bytes).
Voorbeeld 1: Shellcommando's uitvoeren:
import subprocess
result = subprocess.run("dir", shell=True, capture_output=True, text=True)
print(result.stdout)
Uitvoer:
Volume in drive C has no label.
Volume Serial Number is E414-A41C
Directory of C:\Users\owner
01/25/2023 10:56 AM <DIR> .
01/25/2023 10:56 AM <DIR> ..
07/19/2021 01:19 PM <DIR> .anaconda
07/19/2021 01:19 PM <DIR> .astropy
07/19/2021 01:19 PM <DIR> .aws
09/12/2022 08:48 AM 496 .bash_history
03/27/2022 03:08 PM <DIR> .cache
09/26/2021 06:58 AM <DIR> .conda
09/26/2021 06:59 AM 25 .condarc
…
Op Linux/macOS gebruik je: result = subprocess.run(["ls", "-la"], capture_output=True, text=True) (geen shell-argument nodig).
Voorbeeld 2: Python-scripts uitvoeren:
Je kunt ook een Python-script uitvoeren met de methode subprocess.run(). Laten we beginnen met het maken van een simpel Python-script in een .py-bestand
print(“This is the output from subprocess module”)
Sla dit bestand op als file_donot_exist.py. Nu kun je de module subprocess gebruiken om dit bestand uit te voeren:
import subprocess
import sys
result = subprocess.run(["python", "file_donot_exist.py"], capture_output=True, text=True, check=False)
print(result.stdout)
Uitvoer:
This is the output from subprocess module
Voorbeeld 3: Python-code direct vanuit een functie uitvoeren:
Voor eenvoudige use-cases kun je direct een Python-commando meegeven aan de functie subprocess.run(). Zo doe je dat:
result = subprocess.run([sys.executable, "-c", "print('This is directly from a subprocess.run() function')"], capture_output = True, text = True)
print(result.stdout)
Uitvoer:
This is directly from a subprocess.run() function
In de lijst args verwijst het eerste element sys.executable dynamisch naar het pad van de huidige Python-interpreter. Dit zorgt voor consistentie met het draaiende proces en voorkomt hardgecodeerde paden zoals "C:/...". Het tweede element, "-c", voert de volgende string uit als Python-code in plaats van als script. Voeg altijd import sys toe om toegang te krijgen tot sys.executable.
Voorbeeld 4: Het argument check gebruiken
Het argument check is een optioneel argument van de functie subprocess.run() in de Python subprocess-module. Het is een boolean die bepaalt of de functie de returncode van het uitgevoerde commando moet controleren.
Als check op True staat, controleert de functie de returncode van het commando en wordt een uitzondering CalledProcessError opgegooid als de returncode niet nul is. De uitzondering bevat de returncode, stdout, stderr en het commando als attributen.
Als check op False staat (standaard), gooit de functie geen uitzondering op, zelfs niet als het commando faalt — in plaats daarvan moet je zelf de returncode inspecteren.
import subprocess
result = subprocess.run(["python", "file_donot_exist.py"], capture_output=True, text=True, check=True)
print(result.stdout)
print(result.stderr)
Uitvoer:
---------------------------------------------------------------------------
CalledProcessError Traceback (most recent call last)
<ipython-input-81-503b60184db8> in <module>
1 import subprocess
----> 2 result = subprocess.run(["python", "file_donot_exist.py"], capture_output=True, text=True, check=True)
3 print(result.stdout)
4 print(result.stderr)
~\anaconda3\lib\subprocess.py in run(input, capture_output, timeout, check, *popenargs, **kwargs)
514 retcode = process.poll()
515 if check and retcode:
--> 516 raise CalledProcessError(retcode, process.args,
517 output=stdout, stderr=stderr)
518 return CompletedProcess(process.args, retcode, stdout, stderr)
CalledProcessError: Command '['python', 'file_donot_exist.py']' returned non-zero exit status 2.
Let op dat het commando is mislukt omdat my_python_file2.py niet bestaat, en omdat check=True was meegegeven, is er een CalledProcessError opgegooid. Als je check=False instelt (of het helemaal weglaat), gooit je proces geen uitzondering op; in plaats daarvan zie je de foutmelding in stderr en kun je zelf bepalen hoe je die afhandelt.
import subprocess
result = subprocess.run(["python", "my_python_file2.py"], capture_output=True, text=True, check=False)
print(result.stdout)
print(result.stderr)
Uitvoer:
python: can't open file 'my_python_file2.py': [Errno 2] No such file or directory
python subprocess Popen
subprocess.Popen() is een laagdrempeliger interface voor het draaien van subprocessen, terwijl subprocess.run een hoger-niveau wrapper rond Popen is die bedoeld is om gemakkelijker te gebruiken.
Popen laat je een nieuw proces starten en ermee interacteren via standaardinvoer, -uitvoer en -fout. Het retourneert een handle naar het draaiende proces, die je kunt gebruiken om te wachten tot het proces klaar is, de returncode te controleren of het te beëindigen.
run() is een handigere functie waarmee je een commando kunt draaien en de uitvoer in één keer kunt opvangen, zonder zelf een Popen-object te maken en de streams te beheren. Je kunt ook verschillende opties meegeven, zoals of er een uitzondering moet worden opgegooid als het commando faalt.
In het algemeen gebruik je run() als je gewoon een commando wilt draaien en de uitvoer wilt opvangen, en Popen als je meer controle over het proces nodig hebt, zoals interactie met de invoer- en uitvoerstreams.
De klasse Popen neemt dezelfde argumenten als run(), waaronder args die het uit te voeren commando specificeren, en andere optionele argumenten zoals stdin, stdout, stderr, shell, cwd en env. Ook heeft de klasse Popen verschillende methoden waarmee je met het proces kunt interacteren, zoals communicate(), poll(), wait(), terminate() en kill().
import subprocess
p = subprocess.Popen(["python", "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
output, errors = p.communicate()
print(output)
Uitvoer:
usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Options and arguments (and corresponding environment variables):
-b : issue warnings about str(bytes_instance), str(bytearray_instance)
and comparing bytes/bytearray with str. (-bb: issue errors)
-B : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x
-c cmd : program passed in as string (terminates option list)
-d : debug output from parser; also PYTHONDEBUG=x
-E : ignore PYTHON* environment variables (such as PYTHONPATH)
…
Dit voert het commando python –help uit en maakt een nieuw Popen-object aan, opgeslagen in de variabele p. De standaarduitvoer en -fout van het commando worden opgevangen met de methode communicate() en respectievelijk opgeslagen in de variabelen output en errors.
subprocess.Popen is nuttig wanneer je meer controle over het proces wilt, zoals invoer sturen, uitvoer ontvangen of wachten tot het is voltooid.
python subprocess call
subprocess.call() is een functie in de Python subprocess-module die wordt gebruikt om een commando in een apart proces uit te voeren en te wachten tot het klaar is. Het retourneert de returncode van het commando, die nul is als het commando succesvol was, en niet-nul als het is mislukt.
De functie call() neemt dezelfde argumenten als run(), waaronder args die het uit te voeren commando specificeren, en andere optionele argumenten zoals stdin, stdout, stderr, shell, cwd en env.
De standaarduitvoer en -fout van het commando gaan naar dezelfde stdout en stderr als het ouderproces, tenzij je ze omleidt met de argumenten stdout en stderr.
import sys
import subprocess
return_code = subprocess.call([sys.executable, "--version"])
if return_code == 0:
print("Command executed successfully.")
else:
print("Command failed with return code", return_code)
Uitvoer:
Command executed successfully.
Dit voert het commando python -–version uit in een apart proces en wacht tot het is voltooid. De returncode van het commando wordt opgeslagen in de variabele return_code, die nul is als het commando succesvol was, en niet-nul als het is mislukt.
subprocess.call() is handig wanneer je een commando wilt uitvoeren en de returncode wilt controleren, maar de uitvoer niet hoeft op te vangen.
python subprocess check_output
check_output is een functie in de subprocess-module die lijkt op run(), maar alleen de standaarduitvoer van het commando retourneert en een uitzondering CalledProcessError opgooit als de returncode niet nul is.
De functie check_output() neemt dezelfde argumenten als run(), inclusief args (het uit te voeren commando) en optionele argumenten zoals stdin, stderr, shell, cwd en env. Het retourneert de standaarduitvoer van het commando als een bytes-object of string (als text=True). Het gooit CalledProcessError op als het commando faalt (exitstatus niet nul).
Let op: Standaard vangt check_output() alleen stdout op. Om stderr in de uitvoer op te nemen, leid je het expliciet om met stderr=subprocess.STDOUT.
import subprocess
import sys
try:
output = subprocess.check_output([sys.executable, "--version"], text=True)
print(output)
except subprocess.CalledProcessError as e:
print(f"Command failed with return code {e.returncode}")
Uitvoer:
Python 3.8.8
Python Subprocess Pipe
De Python subprocess-module biedt een manier om kindprocessen te maken en ermee te interacteren, die je kunt gebruiken om andere programma's of commando's uit te voeren. Een van de features van de subprocess-module is de mogelijkheid om pipes te maken, die communicatie tussen ouder- en kindprocessen mogelijk maken.
Een pipe is een unidirectioneel communicatiekanaal dat de standaarduitvoer van het ene proces verbindt met de standaardinvoer van een ander. Een pipe kan de uitvoer van het ene commando verbinden met de invoer van een ander, zodat de uitvoer van het eerste commando als invoer voor het tweede wordt gebruikt.
Pipes kunnen worden gemaakt met de subprocess-module via de klasse Popen door het argument stdout of stdin als subprocess.PIPE op te geven.
Het volgende voorbeeld maakt bijvoorbeeld een pipe die de uitvoer van het commando ls verbindt met de invoer van het commando grep, dat de uitvoer filtert om alleen regels te tonen die het woord "file" bevatten:
import subprocess
ls_process = subprocess.Popen(["ls"], stdout=subprocess.PIPE, text=True)
grep_process = subprocess.Popen(
["grep", "sample"],
stdin=ls_process.stdout,
stdout=subprocess.PIPE,
text=True
)
ls_process.stdout.close() # POSIX-only: prevents deadlocks by closing the pipe
output, error = grep_process.communicate()
print(output)
print(error)
Uitvoer:
sample_data
In dit voorbeeld wordt de klasse Popen gebruikt om twee kindprocessen te maken: één voor het ls-commando en één voor het grep-commando. De stdout van het ls-commando is verbonden met de stdin van het grep-commando via subprocess.PIPE, wat een pipe tussen de twee processen creëert. De methode communicate() wordt gebruikt om de uitvoer van het ls-commando naar het grep-commando te sturen en de gefilterde uitvoer op te halen.
Conclusie
De Python-subprocess-module biedt een krachtige en flexibele manier om kindprocessen te creëren en ermee te interacteren, zodat je andere programma's kunt draaien of commando's kunt geven vanuit je Python-script. Van eenvoudige commando's zoals subprocess.call() tot geavanceerdere features zoals pipes, invoer en uitvoer omleiden en omgevingsvariabelen meegeven: de subprocess-module heeft bijna voor elke use-case wel iets te bieden. Het is een geweldige manier om repetitieve taken te automatiseren, systeemcommando's uit te voeren en zelfs te interacteren met andere programmeertalen en platforms.
Bij het werken met de subprocess-module is het belangrijk te onthouden dat het uitvoeren van externe commando's een beveiligingsrisico kan vormen, vooral bij het gebruik van de parameter shell=True of het doorgeven van niet-geschoonde invoer. Het is altijd een goed idee om de functie subprocess.run() te gebruiken, waarmee je verschillende opties kunt opgeven voor hoe het commando moet worden uitgevoerd, zoals of er een uitzondering moet worden opgegooid als het commando faalt.
Als je dieper wilt duiken in de eindeloze mogelijkheden voor command line-automatisering met Python, bekijk dan onze cursus Command Line Automation in Python. In deze cursus leer je automatiseringscode te schrijven die door een bestandssysteem bladert, zoekt naar bestanden die aan een patroon voldoen en vervolgens bepaalt of bestanden duplicaten zijn in een van de vele gevallen. Na afloop van de cursus kun je Unix-processen beheren en aansturen en allerlei routinematige bestandssysteemactiviteiten automatiseren.
Boost de Python-skills van je team met DataCamp for Business
Als jij of je team je vaardigheden in Python en commandline-automatisering willen verbeteren, overweeg dan DataCamp for Business. DataCamp biedt leeroplossingen op maat voor teams van elke grootte en helpt bedrijven voorop te blijven in het snel veranderende techlandschap. Met DataCamp for Business kun je je team upskillen met cursussen en aangepaste leerpaden die zijn ontworpen om expertise op te bouwen in Python, automatisering en andere essentiële data science-tools. Of je nu een startup of een enterprise bent, DataCamp for Business biedt de middelen en flexibiliteit om de leerdoelen van je team te behalen. Vraag vandaag nog een demo aan voor meer info.
Python Subprocess FAQ's
Wat is het verschil tussen subprocess.call() en subprocess.run()?
subprocess.call() is een functie die een commando uitvoert en wacht tot het klaar is, en de returncode van het commando retourneert. subprocess.run() is een krachtigere functie waarmee je een commando kunt uitvoeren, de uitvoer kunt opvangen en verschillende opties kunt opgeven voor hoe het commando moet worden uitgevoerd, zoals of er een uitzondering moet worden opgegooid als het commando faalt.
Hoe kan ik een commando uitvoeren en de uitvoer opvangen in Python met subprocess?
Je kunt de functie subprocess.run() gebruiken om een commando uit te voeren en de uitvoer in één keer op te vangen. Het volgende voorbeeld draait bijvoorbeeld het commando ls en vangt de uitvoer op in de variabele result:
import subprocess
result = subprocess.run(["ls"], stdout=subprocess.PIPE)
print(result.stdout.decode())
Hoe kan ik variabelen als argumenten doorgeven aan een commando in een subprocess?
Je kunt variabelen als argumenten aan een commando doorgeven in subprocess door ze op te nemen in de lijst die je meegeeft aan de functies subprocess.run() of subprocess.Popen(). In het volgende voorbeeld draait de code het commando echo en geeft daarbij de waarde van de variabele message door als argument:
import subprocess
message = "Hello, World!"
subprocess.run(["echo", message])
Hoe kan ik de uitvoer van een commando omleiden naar een bestand met subprocess?
Je kunt de uitvoer van een commando naar een bestand omleiden met de operator > in het commando. In het volgende voorbeeld draait de code het commando ls en leidt de uitvoer om naar een bestand met de naam ls.txt:
import subprocess
subprocess.run("ls > ls.txt", shell=True)Hoe kan ik een commando op de achtergrond draaien met subprocess?
Je kunt een commando op de achtergrond draaien door de parameter start_new_session op True te zetten bij het maken van een nieuw proces met subprocess.Popen(). Dit maakt een nieuwe process group aan, waardoor je het commando op de achtergrond kunt draaien.
import subprocess
subprocess.Popen(["ls"], start_new_session=True)
Hoe kan ik de returncode controleren van een commando dat met subprocess is uitgevoerd?
Je kunt de returncode van een commando controleren door het attribuut returncode te bekijken van het object subprocess.CompletedProcess dat wordt geretourneerd door subprocess.run(). In het volgende voorbeeld draait de code het commando ls en controleert de returncode:
import subprocess
result = subprocess.run(["ls"])
if result.returncode == 0:
print("Command ran successfully")
else:
print("Command failed with error code", result.returncode)
Hoe kan ik omgevingsvariabelen doorgeven aan een commando dat met subprocess wordt uitgevoerd?
Je kunt omgevingsvariabelen doorgeven aan een commando door ze in een dictionary op te nemen en die dictionary als de parameter env mee te geven bij het maken van een nieuw proces met subprocess.Popen() of subprocess.run(). In het volgende voorbeeld wordt de omgevingsvariabele TEST_VAR ingesteld en het commando printenv uitgevoerd:
import subprocess
env = {'TEST_VAR': 'test_value'}
subprocess.run(["printenv", "TEST_VAR"], env=env)

