Python subprocess est un module qui vous permet de commander, d’exécuter et d’évaluer des pro­grammes externes à l’intérieur du code. Les deux fonctions prin­ci­pales de cet outil sont run() et Popen().

Qu’est-ce que le module Python subprocess ?

Le module Python subprocess fait partie de l’in­ven­taire du langage de pro­gram­ma­tion depuis la version 2.4. Il s’agit d’un outil très complet et puissant que vous pouvez utiliser pour exécuter d’autres pro­grammes ou commandes dans votre code. Il permet non seulement d’ouvrir des pro­grammes, mais aussi de contrôler et d’ajuster le flux de données. Python subprocess offre de nom­breuses méthodes et fonctions, dont nous allons examiner les plus im­por­tantes dans cet article et les expliquer à l’aide d’exemples pratiques.

Managed Nextcloud de IONOS Cloud
Tra­vail­lez en équipe dans votre propre Cloud
  • Sécurité des données
  • Outils de col­la­bo­ra­tion intégrés
  • Hé­ber­ge­ment dans des data centers européens

Python subprocess : fonc­tion­ne­ment avec run()

Com­men­çons par jeter un coup d’œil sur la structure et le fonc­tion­ne­ment de base du subprocess de Python. Ce module est utilisé pour exécuter des sous-processus : Python fonc­tionne alors selon une hié­rar­chie parent-enfant, et prend le rôle de parent qui crée un processus enfant. La fonction la plus utilisée dans le module est run(). Elle vous permet de lancer un processus via Python et ne commence les étapes suivantes que lorsque celui-ci a été en­tiè­re­ment exécuté.

Exemple de fonc­tion­ne­ment de subprocess en Python avec run()

Nous allons main­te­nant utiliser cette fonction pour notre premier exemple du fonc­tion­ne­ment de Python subprocess. Pour cela, on importe d’abord les modules subprocess et sys, puis nous exécutons une simple requête. Le code cor­res­pon­dant ressemble à ceci :

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

La sortie est alors la suivante :

bonjour
python
  • subprocess.run : il s’agit de la fonction pro­pre­ment dite. Elle reçoit une liste de chaînes de ca­rac­tères contenant la commande à exécuter. run() exécute alors un nouveau programme Python.
  • sys.executable : c’est le chemin absolu qui mène au fichier Python avec lequel vous avez ini­tia­le­ment appelé votre programme. Un tel chemin pourrait res­sem­bler à /local/utilisateur/bin/exemple.
  • -c : -c est une option de ligne de commande avec laquelle la chaîne de ca­rac­tères men­tion­née est transmise pour exécution. Pour notre exemple, il s’agit d’un programme qui affiche le mot « bonjour ».

Exécuter Python subprocess avec un script

Pour tester la façon dont vous utilisez le module pour un script que vous avez créé, vous pouvez essayer l’exemple suivant. Créez tout d’abord un script simple au format .py et en­re­gis­trez-le en tant que « exem­ples­cript.py » :

print("Il fait beau aujourd’hui")
python

Pour exécuter ensuite ce fichier avec Python subprocess, utilisez le code suivant :

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

La sortie cor­res­pon­dante res­sem­blera alors à ceci :

Il fait beau aujourd’hui
python

Ouvrir des pro­grammes externes

En principe, il est possible d’ouvrir n’importe quel programme avec Python subprocess et la fonction run(). La seule condition est de connaître le nom exact ou le chemin d’accès de ce programme sur votre système. Par exemple, dans le code suivant, nous ouvrons Notepad :

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

CompletedProcess et capture des sorties externes

Après ces exemples simples, nous allons désormais nous in­té­res­ser à la capture d’une sortie externe. Pour cela, vous exécutez un programme externe avec Python subprocess comme ci-dessus, mais vous recevez en retour un objet appelé CompletedProcess. Nous avons déjà briè­ve­ment intégré les adap­ta­tions né­ces­saires dans un exemple plus haut, nous allons main­te­nant les détailler. Notre point de départ est à nouveau notre premier code, mais avec quelques adap­ta­tions :

import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "print('bonjour')"], capture_output=True, text=True)
print("La sortie par défaut est :", result.stdout)
print("L’erreur par défaut est :", result.stderr)
python

Une fois de plus, nous demandons au système d’afficher la chaîne de ca­rac­tères « bonjour » au sein d’un processus enfant. Les deux arguments de mots-clés capture_output=True et text=True, que nous passons également à run(), sont nouveaux. Si l’ins­truc­tion est exécutée et qu’il n’y a pas d’erreur, vous obtenez un objet CompletedProcess avec une liaison à result. Cet objet contient des in­for­ma­tions sur le code de sortie du programme que vous voulez exécuter et les transmet à result.stdout et result.stderr. stdout indique la sortie par défaut et stderr les éven­tuelles erreurs par défaut. Nous utilisons text=True pour imprimer la sortie sous forme de chaîne de ca­rac­tères. Comme aucune erreur standard n’est attendue, notre résultat est le suivant :

La sortie par défaut est : bonjour
L’erreur par défaut est :
python

Nous allons désormais modifier l’exemple précédent de manière à ce que stderr ne soit pas vide. Voici le code cor­res­pon­dant :

import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "raise ValueError('erreur')"], capture_output=True, text=True)
print("La sortie par défaut est :", result.stdout)
print("L’erreur par défaut est :", result.stderr)
python

Alors que la sortie standard reste vide, il y a main­te­nant une sortie pour stderr :

La sortie par défaut est :
L’erreur par défaut est : Traceback (most recent call last):
File "<string>", line 1, in <module>
ValueError: erreur
python

Exécution à partir d’une fonction

Si vous voulez inclure une commande di­rec­te­ment dans le code, Python subprocess vous offre cette option. Dans ce cas, le code pourrait res­sem­bler à cet exemple :

import subprocess
result = subprocess.run(["C:/Users/name/anaconda3/python", "-c", "print('Cette sortie a été prise directement depuis une fonction')"], capture_output=True, text=True, shell=True)
print("La sortie par défaut est :", result.stdout)
python

La sortie est alors la suivante :

La sortie par défaut est : Cette sortie a été prise directement depuis une fonction
python

Arrêter ou terminer des processus

Une autre uti­li­sa­tion très utile de Python subprocess est obtenue par l’in­te­rac­tion de run() avec l’argument timeout. Il vous permet d’arrêter un programme externe si son exécution prend trop de temps. Pour cela, utilisez la fonction time.sleep. Le code approprié est le suivant :

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

Le processus enfant utilise time.sleep pour s’arrêter pendant trois secondes. Cependant, comme vous avez demandé au système de dé­clen­cher un timeout après une seconde via timeout=1, le résultat est une exception TimeoutExpired.

Python subprocess avec Popen()

Bien que run() soit la fonction de subprocess de Python la plus utilisée, il existe également d’autres classes Python im­por­tantes qui peuvent se révéler très utiles. Parmi elles, on trouve Popen(). Cette classe est en quelque sorte le sous-ensemble de subprocess et est un peu plus complexe à utiliser que run(). En revanche, Popen() vous donne plus de contrôle sur l’exécution et vous permet d’interagir avec l’entrée et la sortie. Cette classe doit son nom à une commande UNIX et signifie « pipe open » (lit­té­ra­le­ment « tuyau ouvert »).

Presque tous les arguments que vous pouvez utiliser avec run() sont autorisés avec Popen(). Cependant, con­trai­re­ment à run(), cette fonction n’attend pas la fin d’un processus : elle en lance un second en parallèle. Voici un exemple simple :

import subprocess
from time import sleep
def poll_and_read(process):
    print(f"Voici la sortie après poll(): {process.poll()}")
    print(f"Voici la sortie par défaut : {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"Code de sortie du processus : {process.returncode}")
python

Ici, nous utilisons la méthode .poll() pour vérifier si le processus est toujours en cours ou s’il est déjà terminé. Tant qu’il est encore en cours d’exécution, la valeur « none » est affichée. Ensuite, la méthode affiche le code de sortie. Avec .read(), tous les octets qui se trou­vaient jusqu’à présent dans .stdout doivent être lus. Si vous exécutez le code, vous ob­tien­drez d’abord la valeur « none », puis la valeur contenue jusqu’à présent dans stdout. Cela con­ti­nuera jusqu’à ce que le processus soit terminé. poll() reçoit alors la valeur « 0 ».

Conseil

Déployer des ap­pli­ca­tions et des sites Web di­rec­te­ment avec GitHub : avec Deploy Now de IONOS, vous bé­né­fi­ciez d’une con­fi­gu­ra­tion plus rapide, de workflows optimisés et d’une ex­cel­lente évo­lu­ti­vité. Trouvez le tarif le plus adapté à vos besoins !

Aller au menu principal