• Erledigen Sie die Anwendungssicherheit auf die richtige Weise! Erkennen, schützen, überwachen, beschleunigen und mehr…
  • Mit Unterprozessen können Sie auf einer völlig neuen Ebene mit dem Betriebssystem interagieren.

    Unser Computer führt ständig Unterprozesse aus. Wenn Sie diesen Artikel lesen, führen Sie viele Prozesse wie einen Netzwerkmanager oder den Internetbrowser selbst aus.

    Das Coole daran ist, dass jede Aktion, die wir auf unserem Computer ausführen, das Aufrufen eines Unterprozesses beinhaltet. Das bleibt auch dann wahr, wenn wir ein einfaches schreiben "Hallo Welt" Skript in python.

    Das Konzept der Unterprozess kann dunkel erscheinen, selbst wenn Sie eine Weile Programmieren gelernt haben. Dieser Artikel befasst sich eingehend mit dem Hauptkonzept des Unterprozesses und der Verwendung von Python Unterprozess-Standardbibliothek.

    Am Ende dieses Tutorials werden Sie:

    • Verstehen Sie das Konzept des Teilprozesses
    • Haben die Grundlagen der Python-Unterprozessbibliothek gelernt
    • Übte deine Python-Fähigkeiten mit nützlichen Beispielen

    Lassen Sie uns darauf eingehen

    Das Konzept des Teilprozesses

    Im Großen und Ganzen ist ein Teilprozess ein Computerprozess erstellt durch einen anderen Prozess.

    Wir können uns einen Unterprozess als einen Baum vorstellen, in dem jeder übergeordnete Prozess untergeordnete Prozesse hinter sich hat. Ich weiß, dass dies ziemlich verwirrend sein kann, aber lassen Sie es uns mit einer einfachen Grafik sehen.

    Es gibt verschiedene Möglichkeiten, den auf unserem Computer ausgeführten Prozess zu visualisieren. Zum Beispiel haben wir unter UNIX (Linux & MAC) htop, Das ist ein interaktiver Prozess-Viewer.

    Htop Process Viewer

    Das Baummodus ist das nützlichste Werkzeug, um einen Blick auf die laufenden Unterprozesse zu werfen. Wir können es mit aktivieren F5.

    Wenn wir uns den Befehlsabschnitt genauer ansehen, können wir die Struktur der Prozesse feststellen, die auf unserem Computer ausgeführt werden.

    Htop Prozessstruktur
    Alles beginnt mit / sbin / init Mit diesem Befehl wird jeder Prozess auf unserem Computer gestartet. Von diesem Punkt aus können wir den Beginn anderer Prozesse wie sehen xfce4-Screenshoter und der xfce4-terminal (Was zu noch mehr Teilprozessen führt)

    Wenn wir uns Windows ansehen, haben wir das Mythische Task-Manager Dies ist nützlich, wenn Sie diese abstürzenden Programme auf unserem Computer beenden.

    Windows Task-Manager

    Jetzt haben wir ein kristallklares Konzept. Mal sehen, wie wir Unterprozesse in Python implementieren können.

    Unterprozesse in Python

    Ein Unterprozess in Python ist eine Aufgabe, die ein Python-Skript an das Betriebssystem delegiert.

    Mit der Unterprozessbibliothek können wir Unterprozesse direkt in Python ausführen und verwalten. Dazu muss mit der Standardeingabe gearbeitet werden stdin, Standardausgabe stdoutund Rückkehrcodes.

    Wir müssen es nicht mit PIP installieren, da es Teil von Python ist Standardbibliothek.

    Daher können wir mit der Verwendung von Unterprozessen in Python beginnen, indem wir das Modul importieren.

    import subprocess
    
    # Using the module ....

    Hinweis: Um diesem Artikel folgen zu können, sollten Sie Python 3.5 + haben

    Um die aktuelle Python-Version zu überprüfen, führen Sie sie einfach aus.

    ❯ python --version
    Python 3.9.5 # My result
    

    Wenn die Python-Version 2.x ist, können Sie den folgenden Befehl verwenden

    python3 --version

    Wenn Sie mit dem Thema fortfahren, besteht die Hauptidee hinter der Unterprozessbibliothek darin, mit dem Betriebssystem interagieren zu können, indem Sie alle gewünschten Befehle direkt vom Python-Interpreter ausführen.

    Das heißt, wir können tun, was wir wollen, solange unser Betriebssystem dies zulässt (und solange Sie Ihr Root-Dateisystem nicht entfernen 😅).

    Lassen Sie uns sehen, wie Sie es verwenden, indem Sie ein einfaches Skript erstellen, das die Dateien des aktuellen Verzeichnisses auflistet.

    Erste Teilprozessanwendung

    Zuerst erstellen wir eine Datei list_dir.py. Dies ist die Datei, in der wir experimentieren werden, um Dateien aufzulisten.

    touch list_dir.py

    Öffnen wir nun diese Datei und verwenden den folgenden Code.

    import subprocess 
    
    subprocess.run('ls')

    Zuerst importieren wir das Unterprozessmodul und verwenden dann die Funktion Lauf was läuft, der Befehl, den wir als Argument übergeben.

    Diese Funktion wurde in Python 3.5 als benutzerfreundliche Verknüpfung zu eingeführt Unterprozess.Popen. Mit der Funktion subprocess.run können wir einen Befehl ausführen und warten, bis er beendet ist, im Gegensatz zu Popen, wo wir die Option haben, die Kommunikation später aufzurufen.

    Apropos Code-Ausgabe, ls ist ein UNIX-Befehl Hier werden die Dateien des Verzeichnisses aufgelistet, in dem Sie sich befinden. Wenn Sie diesen Befehl ausführen, wird eine Liste der im aktuellen Verzeichnis vorhandenen Dateien angezeigt.

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

    Hinweis: Beachten Sie, dass Sie unter Windows unterschiedliche Befehle verwenden müssen. Zum Beispiel anstatt zu verwenden "Ls"  du kannst benutzen "Dir"

    Dies mag zu einfach erscheinen, und Sie haben Recht. Sie möchten die gesamte Kraft, die Ihnen die Shell bietet, umfassend nutzen. Lassen Sie uns also lernen, wie Argumente mit einem Unterprozess an die Shell übergeben werden.

    Um beispielsweise auch die versteckten Dateien (die mit einem Punkt beginnen) und alle Metadaten der Dateien aufzulisten, schreiben wir den folgenden Code.

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

    Wir führen diesen Befehl als Zeichenfolge aus und verwenden das Argument Schale. Das heißt, wir rufen zu Beginn der Ausführung unseres Unterprozesses eine Shell auf und das Befehlsargument wird direkt von der Shell interpretiert.

    Allerdings ist die Verwendung shell = True hat viele Nachteile, und das Schlimmste sind die möglichen Sicherheitslücken. Sie können darüber in der lesen offizielle Dokumentation.

    Der beste Weg, Befehle an die Ausführungsfunktion zu übergeben, besteht darin, eine Liste zu verwenden, in der lst [0] ist der aufzurufende Befehl (in diesem Fall ls) und lst [n] sind die Argumente dieses Befehls.

    In diesem Fall sieht unser Code folgendermaßen aus.

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

    Wenn wir die Standardausgabe eines Unterprozesses in einer Variablen speichern möchten, können wir dies tun, indem wir das Argument capture_output auf true setzen.

    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'

    Um auf die Ausgabe eines Prozesses zuzugreifen, verwenden wir das Instanzattribut stdout.

    In diesem Fall möchten wir die Ausgabe als Zeichenfolge anstelle von Bytes speichern. Dazu können Sie das Textargument auf true setzen.

    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

    Perfekt, jetzt wo wir die Grundlagen der kennen Unterprozess Bibliothek, es ist Zeit, zu einigen Verwendungsbeispielen überzugehen.

    Verwendungsbeispiele für Unterprozesse in Python

    In diesem Abschnitt werden einige praktische Anwendungen der Unterprozessbibliothek beschrieben. Sie können alle darin überprüfen Github-Repository.

    Programmprüfer

    Eine der Hauptanwendungen dieser Bibliothek ist die Möglichkeit, einfache Betriebssystemoperationen durchzuführen.

    Zum Beispiel ein einfaches Skript, das prüft, ob ein Programm installiert ist. Unter Linux können wir dies mit dem tun welche Befehl.

    '''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)

    Hinweis: Wenn ein Befehl unter UNIX erfolgreich ist, lautet sein Statuscode 0. Andernfalls ist während der Ausführung ein Fehler aufgetreten

    Da wir das nicht benutzen shell = True Argument können wir die Benutzereingaben sicher nehmen. Wir können auch überprüfen, ob die Eingabe ein gültiges Programm mit einem Regex-Muster ist.

    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')
    

    In diesem Fall erhalten wir die Programme vom Benutzer und verwenden einen regulären Ausdruck, der bestätigt, dass die Programmzeichenfolge nur Buchstaben und Ziffern enthält. Wir überprüfen die Existenz jedes Programms mit einer for-Schleife.

    Einfaches Grep in Python

    Dein Freund Tom hat eine Liste von Mustern in einer Textdatei und eine andere große Datei, in der er die Anzahl der Übereinstimmungen für jedes Muster erhalten möchte. Er würde Stunden damit verbringen, das zu leiten grep Befehl für jedes Muster.

    Glücklicherweise wissen Sie, wie Sie dieses Problem mit Python lösen können, und Sie werden ihm helfen, diese Aufgabe in wenigen Sekunden zu erledigen.

    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')
    

     

    Wenn wir uns diese Datei ansehen, definieren wir zwei Variablen, die die Dateinamen sind, mit denen wir arbeiten möchten. Dann öffnen wir die Datei, die alle Muster enthält, und durchlaufen sie. Als nächstes rufen wir einen Unterprozess auf, der einen grep-Befehl mit dem ausführt "-C" Flag (bedeutet Anzahl) und bestimmen Sie die Ausgabe der Übereinstimmung mit einer Bedingung.

    Wenn Sie diese Datei ausführen (denken Sie daran, dass Sie die Textdateien von der herunterladen können Github Repo)

    Richten Sie eine virtuelle Umgebung mit Unterprozess ein

    Eines der coolsten Dinge, die Sie mit Python tun können, ist die Prozessautomatisierung. Diese Art von Skript kann Ihnen Stunden Zeit pro Woche sparen.

    Zum Beispiel werden wir ein Setup-Skript erstellen, das eine virtuelle Umgebung für uns erstellt und versucht, eine zu finden requirements.txt Datei im aktuellen Verzeichnis, um alle Abhängigkeiten zu installieren.

    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 ...")

     

    In diesem Fall verwenden wir mehrere Prozesse und analysieren die Daten, die wir in unserem Python-Skript benötigen. Wir benutzen auch die Pfadlib Bibliothek, die es uns ermöglicht, es herauszufinden, wenn die requirements.txt Datei existiert.

    Wenn Sie die Python-Datei ausführen, erhalten Sie einige nützliche Meldungen darüber, was mit dem Betriebssystem passiert.

    ❯ 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"

    Beachten Sie, dass wir die Ausgabe aus dem Installationsprozess erhalten, da wir die Standardausgabe nicht in eine Variable umleiten.

    Führen Sie eine andere Programmiersprache aus

    Wir können andere Programmiersprachen mit Python ausführen und die Ausgabe aus diesen Dateien erhalten. Dies ist möglich, weil die Teilprozesse direkt mit dem Betriebssystem interagieren.

    Lassen Sie uns zum Beispiel ein Hallo-Welt-Programm in C ++ und Java erstellen. Um die folgende Datei auszuführen, müssen Sie installieren C + + Java Compiler.

    halloworld.cpp

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


    halloworld.java

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


    Ich weiß, dass dies im Vergleich zu einem einfachen Python-Einzeiler viel Code zu sein scheint, aber dies dient nur zu Testzwecken.

    Wir werden ein Python-Skript erstellen, das alle C ++ - und Java-Dateien in einem Verzeichnis ausführt. Dazu möchten wir zunächst eine Liste der Dateien in Abhängigkeit von der Dateierweiterung erhalten und Klacks ermöglicht es uns, es einfach zu machen!

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

    Danach können wir beginnen, Unterprozesse zu verwenden, um jeden Dateityp auszuführen.

    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)

    Ein kleiner Trick ist die Verwendung der String-Funktion abstreifen um die Ausgabe zu ändern und nur das zu bekommen, was wir brauchen.

    Hinweis: Seien Sie vorsichtig, wenn Sie große Java- oder C ++ - Dateien ausführen, da wir deren Ausgabe in den Speicher laden und dies zu einem Speicherverlust führen kann.

    Öffnen Sie externe Programme

    Wir können andere Programme ausführen, indem wir ihren Binärspeicherort über einen Unterprozess aufrufen.

    Probieren wir es aus, indem wir es öffnen trotzen, mein bevorzugter Webbrowser.

    import subprocess
    
    subprocess.run('brave')

    Dadurch wird eine Browserinstanz oder nur eine andere Registerkarte geöffnet, wenn Sie den Browser bereits ausgeführt haben.

    Geöffneter Browser

    Wie bei jedem anderen Programm, das Flags akzeptiert, können wir sie verwenden, um das gewünschte Verhalten zu erzeugen.

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

    Inkognito-Flagge

    Um zusammenzufassen

    Ein Unterprozess ist ein Computerprozess, der von einem anderen Prozess erstellt wurde. Wir können die Prozesse, die auf unserem Computer ausgeführt werden, mit Tools wie htop und dem Task-Manager überprüfen.

    Python hat eine eigene Bibliothek, um mit Unterprozessen zu arbeiten. Derzeit ist die Lauf Die Funktion bietet uns eine einfache Schnittstelle zum Erstellen und Verwalten von Unterprozessen.

    Wir können mit ihnen jede Art von Anwendung erstellen, da wir direkt mit dem Betriebssystem interagieren.

    Denken Sie zum Schluss daran, dass der beste Weg zum Lernen darin besteht, etwas erschaffen du würdest gerne benutzen.