Guide complet du module subprocess de Python | Des bases à l’avancé

1. Qu’est‑ce que le module subprocess de Python ?

Vue d’ensemble

Le module subprocess de Python est un outil puissant pour exécuter des commandes système et des programmes externes depuis Python. En utilisant ce module, vous pouvez gérer les entrées/sorties standard et les processus, ce qui facilite l’intégration de programmes externes avec des scripts Python. Il offre une méthode plus sûre et plus flexible pour contrôler les processus que les modules traditionnels os.system() ou commands.

Principaux cas d’utilisation

  • Exécution de commandes shell : lancer des commandes système simples.
  • Gestion de processus : exécuter des programmes externes et rediriger les entrées/sorties standard.
  • Traitement asynchrone : gérer des tâches de longue durée et une exécution parallèle.
Ad

2. Utilisation de base : subprocess.run()

Utilisation de base

La fonction subprocess.run() vous permet d’exécuter des commandes système depuis Python de façon simple. Par exemple, pour lister les fichiers d’un répertoire, vous pouvez utiliser le code suivant :

import subprocess

result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)

Ce code exécute la commande ls -l, capture sa sortie dans stdout et la traite dans Python. L’option capture_output=True capture la sortie standard, et text=True garantit que le résultat est manipulé comme une chaîne de caractères.

Gestion des erreurs

Lorsque vous utilisez subprocess.run(), vous pouvez récupérer les messages d’erreur via stderr si la commande échoue. Vous pouvez également vérifier le succès de l’exécution avec returncode.

result = subprocess.run(['ls', 'nonexistentfile'], capture_output=True, text=True)
if result.returncode != 0:
    print(f"Error: {result.stderr}")

Dans cet exemple, si un fichier inexistant est indiqué, un message d’erreur sera affiché via la sortie d’erreur standard.

Ad
年収訴求

3. Exécution asynchrone : subprocess.Popen()

Traitement asynchrone avec Popen

Comme subprocess.run() est une opération synchrone, le programme Python ne peut pas passer à l’étape suivante tant que l’exécution de la commande n’est pas terminée. En revanche, avec subprocess.Popen(), vous pouvez lancer des processus de façon asynchrone et effectuer d’autres tâches simultanément.

import subprocess

proc = subprocess.Popen(['sleep', '5'], stdout=subprocess.PIPE)
print("Process started")
proc.wait()
print("Process completed")

Dans ce code, la commande sleep 5 s’exécute de façon asynchrone, permettant à d’autres tâches de continuer pendant son exécution.

Contrôle des entrées et sorties standard

Avec Popen, vous pouvez contrôler précisément la redirection des entrées et sorties standard. Par exemple, le code suivant lit des données depuis un fichier, les traite avec la commande cat, puis écrit le résultat dans un autre fichier.

with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
    proc = subprocess.Popen(['cat'], stdin=infile, stdout=outfile)
    proc.wait()

Cela vous permet de rediriger les entrées et sorties standard des commandes externes vers des fichiers pour les traiter.

Ad

4. Cas d’utilisation : scripts d’automatisation

Sauvegarde de fichiers

Le module subprocess est très utile pour automatiser les tâches de gestion système et les opérations périodiques. Par exemple, le script suivant copie automatiquement des fichiers vers un répertoire de sauvegarde :

import subprocess

files_to_backup = ['file1.txt', 'file2.txt', 'file3.txt']
backup_dir = '/backup/directory/'

for file in files_to_backup:
    subprocess.run(['cp', file, backup_dir])

Ce script copie les fichiers spécifiés dans un dossier de sauvegarde. Créer de simples scripts comme celui‑ci peut aider à automatiser les tâches de sauvegarde récurrentes.

Utilisation dans les pipelines CI/CD

Le module subprocess est également couramment utilisé dans les environnements d’Intégration Continue (CI) et de Déploiement Continu (CD). Il peut être intégré aux pipelines d’automatisation pour exécuter des scripts de test et gérer les processus de déploiement. Par exemple, il peut être utilisé pour lancer automatiquement des scripts de test et ne passer à l’étape suivante que si les tests réussissent.

Ad
侍エンジニア塾

5. Sécurité et bonnes pratiques

Risques de shell=True

The shell=True option est utilisée pour exécuter des commandes via le shell, mais elle comporte des risques de sécurité. En particulier, lorsqu’on transmet directement des entrées externes, il existe un danger d’attaques d’injection de shell. Utiliser shell=False réduit ce risque.

import subprocess

# Recommended usage (safe)
subprocess.run(['ls', '-l'])

# shell=True (use with caution)
subprocess.run('ls -l', shell=True)

Compatibilité multiplateforme

Les commandes système peuvent varier selon les différents systèmes d’exploitation. Vous pouvez utiliser le module platform de Python pour déterminer l’OS et adapter les commandes en conséquence.

import platform
import subprocess

if platform.system() == "Windows":
    subprocess.run(['dir'], shell=True)
else:
    subprocess.run(['ls', '-l'])
Ad

6. Dépannage et débogage

Erreurs courantes et solutions

Lors de l’utilisation de subprocess, des erreurs telles que « file not found » ou « permission denied » sont fréquentes. Elles peuvent être capturées avec stderr, et vous pouvez vérifier returncode pour obtenir des détails sur l’erreur.

Conseils de débogage

L’option check=True lève une exception si la commande échoue, ce qui vous aide à détecter les problèmes rapidement. Capturer la sortie standard et les messages d’erreur pour les journaux facilite également le débogage.

import subprocess

try:
    result = subprocess.run(['ls', '-l'], check=True, capture_output=True, text=True)
    print(result.stdout)
except subprocess.CalledProcessError as e:
    print(f"An error occurred: {e}")
Ad

7. Traitement asynchrone avec asyncio

Traitement asynchrone avec asyncio

En utilisant asyncio, vous pouvez intégrer subprocess à un traitement asynchrone, permettant à plusieurs processus de s’exécuter en parallèle. L’exemple ci‑dessous exécute la commande ls de façon asynchrone et capture sa sortie.

import asyncio
import subprocess

async def run_command():
    proc = await asyncio.create_subprocess_exec('ls', '-l',
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)

    stdout, stderr = await proc.communicate()

    if stdout:
        print(f'[stdout]n{stdout.decode()}')
    if stderr:
        print(f'[stderr]n{stderr.decode()}')

asyncio.run(run_command())

Ce code exécute la commande de façon asynchrone et traite la sortie standard ainsi que la sortie d’erreur. L’utilisation de asyncio permet une gestion efficace des tâches asynchrones.

Ad
RUNTEQ(ランテック)|超実戦型エンジニア育成スクール