# Python subprocess : exécuter des commandes et des programmes externes

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](https://www.ionos.fr/digitalguide/sites-internet/developpement-web/langages-de-programmation-web/) 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.

## 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 :

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

La sortie est alors la suivante :

```python
bonjour
```

- `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 » :

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

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

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

La sortie correspondante ressemblera alors à ceci :

```python
Il fait beau aujourd’hui
```

## 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 :

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

## `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 :

```python
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)
```

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 :

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

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

```python
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)
```

Alors que la sortie standard reste vide, il y a maintenant une sortie pour `stderr` :

```python
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
```

## 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 :

```python
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)
```

La sortie est alors la suivante :

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

## 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 :

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

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](https://www.ionos.fr/digitalguide/sites-internet/developpement-web/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 :

```python
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}")
```

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](https://www.ionos.fr/hebergement/deploy-now "Deploy Now » Déployez vos projets via GitHub | IONOS") 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 !


This is a markdown version of: [https://www.ionos.fr/digitalguide/sites-internet/developpement-web/python-subprocess/](https://www.ionos.fr/digitalguide/sites-internet/developpement-web/python-subprocess/) for AI/LLM consumption.