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

Qu’est-ce que le module Python subprocess ?

Le module Python subprocess fait partie de l’inventaire du langage de programmation 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 programmes ou commandes dans votre code. Il permet non seulement d’ouvrir des programmes, mais aussi de contrôler et d’ajuster le flux de données. Python subprocess offre de nombreuses méthodes et fonctions, dont nous allons examiner les plus importantes dans cet article et les expliquer à l’aide d’exemples pratiques.

Managed Nextcloud de IONOS Cloud
Travaillez en équipe dans votre propre Cloud
  • Sécurité des données
  • Outils de collaboration intégrés
  • Hébergement dans des data centers européens

Python subprocess : fonctionnement avec run()

Commençons par jeter un coup d’œil sur la structure et le fonctionnement de base du subprocess de Python. Ce module est utilisé pour exécuter des sous-processus : Python fonctionne alors selon une hiérarchie 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é entièrement exécuté.

Exemple de fonctionnement de subprocess en Python avec run()

Nous allons maintenant utiliser cette fonction pour notre premier exemple du fonctionnement de Python subprocess. Pour cela, on importe d’abord les modules subprocess et sys, puis nous exécutons une simple requête. Le code correspondant 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 proprement dite. Elle reçoit une liste de chaînes de caractè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 initialement appelé votre programme. Un tel chemin pourrait ressembler à /local/utilisateur/bin/exemple.
  • -c : -c est une option de ligne de commande avec laquelle la chaîne de caractères mentionné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 enregistrez-le en tant que « exemplescript.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 correspondante ressemblera alors à ceci :

Il fait beau aujourd’hui
python

Ouvrir des programmes 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 intéresser à 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èvement intégré les adaptations nécessaires dans un exemple plus haut, nous allons maintenant les détailler. Notre point de départ est à nouveau notre premier code, mais avec quelques adaptations :

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 caractè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’instruction 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 informations 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 éventuelles erreurs par défaut. Nous utilisons text=True pour imprimer la sortie sous forme de chaîne de caractè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 correspondant :

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 maintenant 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 directement dans le code, Python subprocess vous offre cette option. Dans ce cas, le code pourrait ressembler à 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 utilisation très utile de Python subprocess est obtenue par l’interaction 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éclencher 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 importantes 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 » (littéralement « tuyau ouvert »).

Presque tous les arguments que vous pouvez utiliser avec run() sont autorisés avec Popen(). Cependant, contrairement à 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 trouvaient jusqu’à présent dans .stdout doivent être lus. Si vous exécutez le code, vous obtiendrez d’abord la valeur « none », puis la valeur contenue jusqu’à présent dans stdout. Cela continuera jusqu’à ce que le processus soit terminé. poll() reçoit alors la valeur « 0 ».

Conseil

Déployer des applications et des sites Web directement avec GitHub : avec Deploy Now de IONOS, vous bénéficiez d’une configuration plus rapide, de workflows optimisés et d’une excellente évolutivité. Trouvez le tarif le plus adapté à vos besoins !

Cet article vous a-t-il été utile ?
Aller au menu principal