• Assurez la sécurité des applications de la bonne manière! Détectez, protégez, surveillez, accélérez et plus encore…
  • Les sous-processus vous permettent d'interagir à un niveau totalement nouveau avec le système opérationnel.

    Notre ordinateur exécute des sous-processus tout le temps. En fait, rien qu'en lisant cet article, vous exécutez de nombreux processus comme un gestionnaire de réseau ou le navigateur Internet lui-même.

    La chose intéressante à ce sujet est que toute action que nous faisons sur notre ordinateur implique l'appel d'un sous-processus. Cela reste vrai même si nous écrivons un simple "Bonjour le monde" script dans python.

    Le concept de la sous-processus peut sembler obscur même si vous apprenez la programmation depuis un certain temps. Cet article examinera en profondeur le concept principal du sous-processus et comment utiliser Python bibliothèque standard de sous-processus.

    À la fin de ce didacticiel, vous allez:

    • Comprendre le concept de sous-processus
    • Avoir appris les bases de la bibliothèque de sous-processus Python
    • Pratiquez vos compétences Python avec des exemples utiles

    Entrons dedans

    Le concept de sous-processus

    En gros, un sous-processus est un processus informatique créé par un autre processus.

    Nous pouvons considérer un sous-processus comme une arborescence, dans laquelle chaque processus parent a des processus enfants qui s'exécutent derrière lui. Je sais que cela peut être assez déroutant, mais voyons-le avec un graphique simple.

    Il existe plusieurs façons de visualiser le processus en cours d'exécution sur notre ordinateur. Par exemple, sous UNIX (Linux et MAC), nous avons htop, qui est un visualiseur de processus interactif.

    Visualiseur de processus Htop

    Le mode arborescence est l'outil le plus utile pour examiner les sous-processus en cours d'exécution. Nous pouvons l'activer avec F5.

    Si nous examinons de près la section des commandes, nous pouvons remarquer la structure des processus en cours d'exécution sur notre ordinateur.

    Structure de processus Htop
    Tout commence par / sbin / init qui est la commande qui démarre chaque processus sur notre ordinateur. À partir de là, nous pouvons voir le début d'autres processus comme xfce4-capture d'écran et l’équipe de terminal xfce4 (Ce qui conduit à encore plus de sous-processus)

    Jetant un œil à Windows, nous avons le mythique gestionnaire des tâches ce qui est utile pour tuer ces programmes qui plantent sur notre machine.

    Gestionnaire de tâches Windows

    Maintenant, nous avons un concept clair comme du cristal. Voyons comment nous pouvons implémenter des sous-processus en Python.

    Sous-processus en Python

    Un sous-processus en Python est une tâche qu'un script python délègue au système d'exploitation (OS).

    La bibliothèque de sous-processus nous permet d'exécuter et de gérer des sous-processus directement à partir de Python. Cela implique de travailler avec l'entrée standard stdin, sortie standard stdoutet les codes de retour.

    Nous n'avons pas à l'installer avec PIP, car il fait partie de Python bibliothèque standard.

    Par conséquent, nous pouvons commencer à utiliser des sous-processus en python simplement en important le module.

    import subprocess
    
    # Using the module ....

    A Noter: Pour suivre cet article, vous devriez avoir Python 3.5 +

    Pour vérifier la version de python que vous avez actuellement, exécutez simplement.

    ❯ python --version
    Python 3.9.5 # My result
    

    Dans le cas où la version Python que vous obtenez est 2.x, vous pouvez utiliser la commande suivante

    python3 --version

    En continuant avec le sujet, l'idée principale derrière la bibliothèque de sous-processus est de pouvoir interagir avec le système d'exploitation en exécutant toutes les commandes que nous voulons, directement à partir de l'interpréteur Python.

    Cela signifie que nous pouvons faire ce que nous voulons, tant que notre système d'exploitation nous le permet (et tant que vous ne supprimez pas votre système de fichiers racine 😅).

    Voyons comment l'utiliser en créant un script simple qui répertorie les fichiers du répertoire courant.

    Première application de sous-processus

    Commençons par créer un fichier list_dir.py. Ce sera le fichier dans lequel nous allons tester les fichiers de liste.

    touch list_dir.py

    Maintenant, ouvrons ce fichier et utilisons le code suivant.

    import subprocess 
    
    subprocess.run('ls')

    Tout d'abord, nous importons le module de sous-processus, puis nous utilisons la fonction courir qui s'exécute, la commande que nous passons en argument.

    Cette fonction a été introduite dans Python 3.5, comme un raccourci convivial vers sous-processus.. La fonction subprocess.run nous permet d'exécuter une commande et d'attendre qu'elle se termine, contrairement à Popen où nous avons la possibilité d'appeler communiquez plus tard.

    Parler de la sortie du code, ls est Commande UNIX qui répertorie les fichiers du répertoire dans lequel vous vous trouvez. Par conséquent, si vous exécutez cette commande, vous obtiendrez une liste des fichiers présents dans le répertoire courant.

    ❯ python list_dir.py
    example.py  LICENSE  list_dir.py  README.md

    A Noter: Tenez compte du fait que si vous êtes sous Windows, vous devrez utiliser différentes commandes. Par exemple au lieu d'utiliser «Ls»  vous pouvez utiliser "Dir"

    Cela peut sembler trop simple et vous avez raison. Vous voulez avoir une approche complète de toute la puissance que la coque vous apporte. Apprenons donc à passer des arguments au shell avec un sous-processus.

    Par exemple pour lister également les fichiers cachés (ceux qui commencent par un point), et également lister toutes les métadonnées des fichiers, nous écrivons le code suivant.

    import subprocess
    
    # subprocess.run('ls')  # Simple command
    
    subprocess.run('ls -la', shell=True)

    Nous exécutons cette commande sous forme de chaîne et utilisons l'argument coquille. Cela signifie que nous invoquons un shell au début de l'exécution de notre sous-processus, et que l'argument de commande est interprété directement par le shell.

    Cependant, l'utilisation shell = Vrai présente de nombreux inconvénients, et les pires sont les éventuelles fuites de sécurité. Vous pouvez lire à leur sujet dans le documentation officielle.

    La meilleure façon de passer des commandes à la fonction d'exécution est d'utiliser une liste où lst [0] est la commande à appeler (ls dans ce cas) et lst [n] sont les arguments de cette commande.

    Si nous le faisons, notre code ressemblera à ceci.

    import subprocess
    
    # subprocess.run('ls')  # Simple command
    
    # subprocess.run('ls -la', shell=True) # Dangerous command
    
    subprocess.run(['ls', '-la'])

    Si nous voulons stocker la sortie standard d'un sous-processus dans une variable, nous pouvons le faire en définissant l'argument capture_output sur true.

    list_of_files = subprocess.run(['ls', '-la'], capture_output=True)
    
    print(list_of_files.stdout)
    
    ❯ python list_dir.py 
    b'total 36\ndrwxr-xr-x 3 daniel daniel 4096 may 20 21:08 .\ndrwx------ 30 daniel daniel 4096 may 20 18:03 ..\n-rw-r--r-- 1 daniel daniel 55 may 20 20:18 example.py\ndrwxr-xr-x 8 daniel daniel 4096 may 20 17:31 .git\n-rw-r--r-- 1 daniel daniel 2160 may 17 22:23 .gitignore\n-rw-r--r-- 1 daniel daniel 271 may 20 19:53 internet_checker.py\n-rw-r--r-- 1 daniel daniel 1076 may 17 22:23 LICENSE\n-rw-r--r-- 1 daniel daniel 216 may 20 22:12 list_dir.py\n-rw-r--r-- 1 daniel daniel 22 may 17 22:23 README.md\n'

    Pour accéder à la sortie d'un processus, nous utilisons l'attribut instance Stdout.

    Dans ce cas, nous voulons stocker la sortie sous forme de chaîne, au lieu d'octets et nous pouvons le faire en définissant l'argument de texte sur true.

    list_of_files = subprocess.run(['ls', '-la'], capture_output=True, text=True)
    
    print(list_of_files.stdout)
    
    ❯ python list_dir.py
    total 36
    drwxr-xr-x  3 daniel daniel 4096 may 20 21:08 .
    drwx------ 30 daniel daniel 4096 may 20 18:03 ..
    -rw-r--r--  1 daniel daniel   55 may 20 20:18 example.py
    drwxr-xr-x  8 daniel daniel 4096 may 20 17:31 .git
    -rw-r--r--  1 daniel daniel 2160 may 17 22:23 .gitignore
    -rw-r--r--  1 daniel daniel  271 may 20 19:53 internet_checker.py
    -rw-r--r--  1 daniel daniel 1076 may 17 22:23 LICENSE
    -rw-r--r--  1 daniel daniel  227 may 20 22:14 list_dir.py
    -rw-r--r--  1 daniel daniel   22 may 17 22:23 README.md

    Parfait, maintenant que nous connaissons les bases de la sous-processus bibliothèque, il est temps de passer à quelques exemples d'utilisation.

    Exemples d'utilisation de sous-processus en Python

    Dans cette section, nous allons passer en revue quelques utilisations pratiques de la bibliothèque de sous-processus. Vous pouvez tous les vérifier dans ce Github référentiel.

    Program checker

    L'une des principales utilisations de cette bibliothèque est la possibilité d'effectuer des opérations simples sur le système d'exploitation.

    Par exemple, un simple script qui vérifie si un programme est installé. Sous Linux, nous pouvons le faire avec le qui commander.

    '''Program checker with subprocess'''
    
    import subprocess
    
    program = 'git'
    
    process = subprocess. run(['which', program], capture_output=True, text=True)
    
    if process.returncode == 0: 
        print(f'The program "{program}" is installed')
    
        print(f'The location of the binary is: {process.stdout}')
    else:
        print(f'Sorry the {program} is not installed')
    
        print(process.stderr)

    A Noter: Sous UNIX, lorsqu'une commande réussit, son code d'état est 0. Sinon, une erreur s'est produite lors de l'exécution

    Puisque nous n'utilisons pas le shell = Vrai argument, nous pouvons prendre l'entrée de l'utilisateur en toute sécurité. En outre, nous pouvons vérifier si l'entrée est un programme valide avec un modèle d'expression régulière.

    import subprocess
    
    import re
    
    programs = input('Separe the programs with a space: ').split()
    
    secure_pattern = '[\w\d]'
    
    for program in programs:
    
        if not re.match(secure_pattern, program):
            print("Sorry we can't check that program")
    
            continue
    
        process = subprocess. run(
            ['which', program], capture_output=True, text=True)
    
        if process.returncode == 0:
            print(f'The program "{program}" is installed')
    
            print(f'The location of the binary is: {process.stdout}')
        else:
            print(f'Sorry the {program} is not installed')
    
            print(process.stderr)
    
        print('\n')
    

    Dans ce cas, nous obtenons les programmes de l'utilisateur et utilisons une expression regex qui certifie que la chaîne du programme ne comprend que des lettres et des chiffres. Nous vérifions l'existence de chaque programme avec une boucle for.

    Simple Grep in Python

    Ton ami Tom a une liste de modèles dans un fichier texte et un autre gros fichier dans lequel il veut obtenir le nombre de correspondances pour chaque modèle. Il passerait des heures à courir le commande grep pour chaque modèle.

    Heureusement, vous savez comment résoudre ce problème avec Python, et vous l'aiderez à accomplir cette tâche en quelques secondes.

    import subprocess
    
    patterns_file = 'patterns.txt'
    readfile = 'romeo-full.txt'
    
    with open(patterns_file, 'r') as f:
        for pattern in f:
            pattern = pattern.strip()
    
            process = subprocess.run(
                ['grep', '-c', f'{pattern}', readfile], capture_output=True, text=True)
    
            if int(process.stdout) == 0:
                print(
                    f'The pattern "{pattern}" did not match any line of {readfile}')
    
                continue
    
            print(f'The pattern "{pattern}" matched {process.stdout.strip()} times')
    

     

    En regardant ce fichier, nous définissons deux variables qui sont les noms de fichiers avec lesquels nous voulons travailler. Ensuite, nous ouvrons le fichier qui contient tous les modèles et nous les parcourons. Ensuite, nous appelons un sous-processus qui exécute une commande grep avec le "-C" flag (signifie count) et déterminer la sortie de la correspondance avec un conditionnel.

    Si vous exécutez ce fichier (n'oubliez pas que vous pouvez télécharger les fichiers texte à partir du Github repo)

    Set up a virtualenv with subprocess

    L'automatisation des processus est l'une des choses les plus intéressantes que vous puissiez faire avec Python. Ce type de script peut vous faire gagner des heures par semaine.

    Par exemple, nous allons créer un script d'installation qui crée un environnement virtuel pour nous et essaie de trouver un conditions.txt dans le répertoire courant pour installer toutes les dépendances.

    import subprocess
    
    from pathlib import Path
    
    
    VENV_NAME = '.venv'
    REQUIREMENTS = 'requirements.txt'
    
    process1 = subprocess.run(['which', 'python3'], capture_output=True, text=True)
    
    if process1.returncode != 0:
        raise OSError('Sorry python3 is not installed')
    
    python_bin = process1.stdout.strip()
    
    print(f'Python found in: {python_bin}')
    
    process2 = subprocess.run('echo "$SHELL"', shell=True, capture_output=True, text=True)
    
    shell_bin = process2.stdout.split('/')[-1]
    
    create_venv = subprocess.run([python_bin, '-m', 'venv', VENV_NAME], check=True)
    
    if create_venv.returncode == 0:
        print(f'Your venv {VENV_NAME} has been created')
    
    pip_bin = f'{VENV_NAME}/bin/pip3'
    
    if Path(REQUIREMENTS).exists():
        print(f'Requirements file "{REQUIREMENTS}" found')
        print('Installing requirements')
        subprocess.run([pip_bin, 'install', '-r', REQUIREMENTS])
    
        print('Process completed! Now activate your environment with "source .venv/bin/activate"')
    
    else:
        print("No requirements specified ...")

     

    Dans ce cas, nous utilisons plusieurs processus et analysons les données dont nous avons besoin dans notre script python. Nous utilisons également le pathlib bibliothèque qui nous permet de le comprendre si le conditions.txt le fichier existe.

    Si vous exécutez le fichier python, vous obtiendrez des messages utiles sur ce qui se passe avec le système d'exploitation.

    ❯ python setup.py 
    Python found in: /usr/bin/python3
    Your venv .venv has been created
    Requirements file "requirements.txt" found
    Installing requirements
    Collecting asgiref==3.3.4 .......
    Process completed! Now activate your environment with "source .venv/bin/activate"

    Notez que nous obtenons la sortie du processus d'installation car nous ne redirigeons pas la sortie standard vers une variable.

    Run another Programming Language

    Nous pouvons exécuter d'autres langages de programmation avec python et obtenir la sortie de ces fichiers. Ceci est possible car les sous-processus interagissent directement avec le système opérationnel.

    Par exemple, créons un programme hello world en C ++ et Java. Afin d'exécuter le fichier suivant, vous devrez installer C + + reçues par les enchanteurs et permettent aussi Java compilateurs.

    helloworld.cpp

    #include <iostream>
    
    int main(){
        std::cout << "This is a hello world in C++" << std::endl;
        return 0;
    }


    helloworld.java

    class HelloWorld{  
        public static void main(String args[]){  
         System.out.println("This is a hello world in Java");  
        }  
    }  


    Je sais que cela semble beaucoup de code par rapport à un simple one-liner Python, mais c'est juste à des fins de test.

    Nous allons créer un script Python qui exécute tous les fichiers C ++ et Java dans un répertoire. Pour ce faire, nous voulons d'abord obtenir une liste de fichiers en fonction de l'extension de fichier, et glob nous permet de le faire facilement!

    from glob import glob
    
    # Gets files with each extension
    java_files = glob('*.java')
    
    cpp_files = glob('*.cpp')

    Après cela, nous pouvons commencer à utiliser des sous-processus pour exécuter chaque type de fichier.

    for file in cpp_files:
        process = subprocess.run(f'g++ {file} -o out; ./out', shell=True, capture_output=True, text=True)
        
        output = process.stdout.strip() + ' BTW this was runned by Python'
    
        print(output)
    
    for file in java_files:
        without_ext = file.strip('.java')
        process = subprocess.run(f'java {file}; java {without_ext}',shell=True, capture_output=True, text=True)
    
        output = process.stdout.strip() + ' A Python subprocess runned this :)'
        print(output)

    Une petite astuce consiste à utiliser la fonction string bande pour modifier la sortie et obtenir uniquement ce dont nous avons besoin.

    A Noter: Soyez prudent d'exécuter de gros fichiers Java ou C ++ car nous chargeons leur sortie en mémoire et cela pourrait produire une fuite de mémoire.

    Open external programs

    Nous sommes en mesure d'exécuter d'autres programmes simplement en appelant leur emplacement binaire via un sous-processus.

    Essayons-le en ouvrant braver, mon navigateur Web préféré.

    import subprocess
    
    subprocess.run('brave')

    Cela ouvrira une instance de navigateur, ou simplement un autre onglet si vous avez déjà exécuté le navigateur.

    Navigateur ouvert

    Comme avec tout autre programme qui accepte les drapeaux, nous pouvons les utiliser pour produire le comportement souhaité.

    import subprocess
    
    subprocess.run(['brave', '--incognito'])

    Indicateur de navigation privée

    Pour résumer

    Un sous-processus est un processus informatique créé par un autre processus. Nous pouvons vérifier les processus exécutés par notre ordinateur avec des outils comme htop et le gestionnaire de tâches.

    Python possède sa propre bibliothèque pour travailler avec des sous-processus. Actuellement, le courir La fonction nous donne une interface simple pour créer et gérer des sous-processus.

    Nous pouvons créer tout type d'application avec eux car nous interagissons directement avec le système d'exploitation.

    Enfin, rappelez-vous que la meilleure façon d'apprendre est de créer quelque chose vous souhaitez utiliser.