Was ist ein Unterprozess in Python? [5 Usage Examples]

Unterprozesse ermöglichen Ihnen die Interaktion auf einer völlig neuen Ebene mit dem Betriebssystem.

Unser Computer führt ständig Unterprozesse aus. Tatsächlich führen Sie allein durch das Lesen dieses Artikels 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 gilt auch dann, wenn wir ein einfaches „Hallo Welt“-Skript in Python schreiben.

Das Konzept des Unterprozesses mag Ihnen obskur erscheinen, selbst wenn Sie das Programmieren schon eine Weile lernen. 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
  • Die Grundlagen der Python-Unterprozessbibliothek gelernt haben
  • Trainieren Sie Ihre Python-Fähigkeiten mit nützlichen Beispielen

Lassen Sie uns darauf eingehen

Das Konzept des Teilprozesses

Allgemein gesagt ist ein Teilprozess a Computerprozess von einem anderen Prozess erstellt.

Wir können uns einen Unterprozess als einen Baum vorstellen, in dem hinter jedem übergeordneten Prozess untergeordnete Prozesse laufen. Ich weiß, dass dies ziemlich verwirrend sein kann, aber sehen wir es uns mit einer einfachen Grafik an.

Es gibt mehrere Möglichkeiten, wie wir den auf unserem Computer ausgeführten Prozess visualisieren können. Zum Beispiel haben wir in UNIX (Linux & MAC). htop, das ist ein interaktiver Prozessbetrachter.

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

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

Alles beginnt mit /sbin/init Dies ist der Befehl, der jeden Prozess auf unserem Computer startet. Von diesem Punkt an können wir den Beginn anderer Prozesse wie xfce4-screenshoter und xfce4-terminal sehen (was zu noch mehr Unterprozessen führt)

Wenn wir uns Windows ansehen, haben wir das Mythische Taskmanager was nützlich ist, wenn diese abstürzenden Programme auf unserem Computer beendet werden.

Jetzt haben wir ein glasklares 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 (OS) delegiert.

Die Unterprozessbibliothek ermöglicht es uns, Unterprozesse direkt aus Python auszuführen und zu verwalten. Dazu gehört die Arbeit mit der Standardeingabe stdin, der Standardausgabe stdout und Rückgabecodes.

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 einfach das Modul importieren.

import subprocess

# Using the module ....

Hinweis: Um diesem Artikel folgen zu können, sollten Sie über Python 3.5 + verfügen

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

❯ python --version
Python 3.9.5 # My result

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

python3 --version

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

Das bedeutet, dass wir tun können, was wir wollen, solange es unser Betriebssystem zulässt (und solange Sie Ihr Root-Dateisystem nicht entfernen 😅).

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

Erste Unterprozessanwendung

Zuerst erstellen wir eine Datei list_dir.py. Dies ist die Datei, in der wir mit dem Auflisten von Dateien experimentieren werden.

touch list_dir.py

Lassen Sie uns nun diese Datei öffnen und den folgenden Code verwenden.

import subprocess 

subprocess.run('ls')

Zuerst importieren wir das Unterprozessmodul und verwenden dann die Funktion run, die ausgeführt wird, den Befehl, den wir als Argument übergeben.

  Debuggen Sie Python wie ein Held mit diesen Bibliotheken und Tools

Diese Funktion wurde in Python 3.5 als freundliche Abkürzung zu eingeführt Unterprozess.Popen. Die Funktion subprocess.run ermöglicht es uns, einen Befehl auszuführen und auf dessen Beendigung zu warten, im Gegensatz zu Popen, wo wir die Option haben, die Kommunikation später aufzurufen.

Apropos Codeausgabe: ls ist ein UNIX-Befehl, der die Dateien des Verzeichnisses auflistet, in dem Sie sich befinden. Wenn Sie diesen Befehl ausführen, erhalten Sie daher eine Liste der Dateien, die im aktuellen Verzeichnis vorhanden sind.

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

Hinweis: Berücksichtigen Sie, dass Sie unter Windows andere Befehle verwenden müssen. Anstelle von „ls“ können Sie beispielsweise „dir“ verwenden

Dies mag zu einfach erscheinen, und Sie haben Recht. Sie möchten die ganze Kraft, die Ihnen die Shell bringt, voll ausschöpfen. Lassen Sie uns also lernen, wie man Argumente mit subprocess an die Shell übergibt.

Um beispielsweise auch die versteckten Dateien aufzulisten (die mit einem Punkt beginnen) und auch 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 Shell. Das bedeutet, dass wir zu Beginn der Ausführung unseres Unterprozesses eine Shell aufrufen und das Befehlsargument direkt von der Shell interpretiert wird.

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

Der beste Weg, Befehle an die run-Funktion zu übergeben, ist die Verwendung einer Liste, in der lst[0] ist der Aufrufbefehl (in diesem Fall ls) und lst[n] sind die Argumente dieses Befehls.

Wenn wir das tun, sieht unser Code so 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 36ndrwxr-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.pyndrwxr-xr-x 8 daniel daniel 4096 may 20 17:31 .gitn-rw-r--r-- 1 daniel daniel 2160 may 17 22:23 .gitignoren-rw-r--r-- 1 daniel daniel 271 may 20 19:53 internet_checker.pyn-rw-r--r-- 1 daniel daniel 1076 may 17 22:23 LICENSEn-rw-r--r-- 1 daniel daniel 216 may 20 22:12 list_dir.pyn-rw-r--r-- 1 daniel daniel 22 may 17 22:23 README.mdn'

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

In diesem Fall möchten wir die Ausgabe als Zeichenfolge statt als Bytes speichern, und wir können dies tun, indem wir das Textargument auf wahr 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, da wir die Grundlagen der Subprozessbibliothek kennen, ist es an der Zeit, mit einigen Anwendungsbeispielen fortzufahren.

  Router-Standard-IP-Adresse und Passwortverwaltung

Verwendungsbeispiele für Unterprozesse in Python

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

Programmprüfer

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

Beispielsweise ein einfaches Skript, das überprüft, ob ein Programm installiert ist. Unter Linux können wir dies mit dem which-Befehl tun.

'''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: Unter UNIX ist der Statuscode eines erfolgreichen Befehls 0. Andernfalls ist während der Ausführung etwas schief gelaufen

Da wir das Argument shell=True nicht verwenden, können wir die Benutzereingabe sicher entgegennehmen. Außerdem können wir prü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 = 'Fr'

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 Regex-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

Ihr Freund Tom hat eine Liste mit Mustern in einer Textdatei und einer weiteren großen Datei, in der er die Anzahl der Übereinstimmungen für jedes Muster abrufen möchte. Er verbrachte Stunden damit, den grep-Befehl für jedes Muster auszuführen.

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 Flag „-c“ (bedeutet Anzahl) ausführt, und bestimmen die Ausgabe der Übereinstimmung mit einer Bedingung.

Wenn Sie diese Datei ausführen (denken Sie daran, dass Sie die Textdateien von der Github-Repository)

Richten Sie eine virtuelle Umgebung mit Unterprozess ein

Eines der coolsten Dinge, die Sie mit Python machen 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 requirements.txt-Datei im aktuellen Verzeichnis zu finden, 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 ...")

  19 erstaunliche Hacks zum Hacken von Roku, um kostenlose Kanäle zu erhalten

In diesem Fall verwenden wir mehrere Prozesse und analysieren die Daten, die wir in unserem Python-Skript benötigen. Wir verwenden auch die pathlib Bibliothek, mit der wir herausfinden können, ob die Datei requirements.txt 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 vom Installationsprozess erhalten, da wir die Standardausgabe nicht auf 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 sie installieren C++ und Java Compiler.

hallowelt.cpp

#include <iostream>

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

hallowelt.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 wollen wir zunächst eine Liste von Dateien erhalten, die von der Dateierweiterung abhängen, und Kugel ermöglicht es uns, es einfach zu tun!

from glob import glob

# Gets files with each extension
java_files = glob('*.java')

cpp_files = glob('*.cpp')

Danach können wir mit der Verwendung von Unterprozessen beginnen, 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 besteht darin, den String-Funktionsstreifen zu verwenden, um die Ausgabe zu ändern und nur das zu erhalten, was wir brauchen.

Hinweis: Achten Sie darauf, große Java- oder C++-Dateien auszuführen, da wir ihre Ausgabe in den Speicher laden und dies zu einem Speicherleck führen könnte.

Öffnen Sie externe Programme

Wir können andere Programme ausführen, indem wir einfach ihren Speicherort für Binärdateien über einen Unterprozess aufrufen.

Probieren wir es aus, indem wir Brave öffnen, meinen bevorzugten Webbrowser.

import subprocess

subprocess.run('brave')

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

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

Um zusammenzufassen

Ein Unterprozess ist ein Computerprozess, der von einem anderen Prozess erstellt wird. 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 bietet uns die Run-Funktion eine einfache Schnittstelle zum Erstellen und Verwalten von Unterprozessen.

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

Denken Sie schließlich daran, dass der beste Weg zu lernen darin besteht, etwas zu erstellen, das Sie verwenden möchten.