Hvad er en underproces i Python? [5 Usage Examples]

Underprocesser lader dig interagere på et helt nyt niveau med operativsystemet.

Vores computer kører underprocesser hele tiden. Faktisk, bare ved at læse denne artikel, kører du en masse processer som en netværksadministrator eller selve internetbrowseren.

Det fede ved dette er, at enhver handling, vi udfører på vores computer, involverer at påkalde en underproces. Det forbliver sandt, selvom vi skriver et simpelt “hej verden”-script i python.

Begrebet underprocessen kan virke uklart, selvom du har lært programmering i et stykke tid. Denne artikel vil tage et dybt kig på hovedkonceptet for underprocessen, og hvordan man bruger Python underproces standardbibliotek.

Ved slutningen af ​​denne vejledning vil du:

  • Forstå begrebet delproces
  • Har lært det grundlæggende i Python-underprocesbiblioteket
  • Øvede dine Python-færdigheder med nyttige eksempler

Lad os komme ind i det

Begrebet delproces

Groft sagt er en delproces en computerproces skabt af en anden proces.

Vi kan tænke på en underproces som et træ, hvor hver overordnede proces har underordnede processer kørende bag sig. Jeg ved, at dette kan være ret forvirrende, men lad os se det med en simpel grafik.

Der er flere måder, vi kan visualisere processen, der kører på vores computer. For eksempel har vi i UNIX (Linux & MAC). htop, som er en interaktiv procesfremviser.

Trætilstanden er det mest nyttige værktøj til at tage et kig på de kørende underprocesser. Vi kan aktivere det med F5.

Hvis vi ser nærmere på kommandoafsnittet, kan vi bemærke strukturen af ​​de processer, der kører på vores computer.

Det hele starter med /sbin/init som er den kommando, der starter hver proces på vores computer. Fra det tidspunkt kan vi se begyndelsen af ​​andre processer som xfce4-screenshoter og xfce4-terminalen (hvilket bidrager til endnu mere underproces)

Tager vi et kig på Windows, har vi det mytiske Jobliste hvilket er nyttigt, når de nedbryder programmer på vores maskine.

Nu har vi et krystalklart koncept. Lad os se, hvordan vi kan implementere underprocesser i Python.

Underprocesser i Python

En underproces i Python er en opgave, som et python-script uddelegerer til operativsystemet (OS).

Underprocesbiblioteket giver os mulighed for at udføre og administrere underprocesser direkte fra Python. Det involverer at arbejde med standard input stdin, standard output stdout og returkoder.

Vi behøver ikke at installere det med PIP, da det er en del af Python standard bibliotek.

Derfor kan vi begynde at bruge underprocesser i python blot ved at importere modulet.

import subprocess

# Using the module ....

Bemærk: For at følge med i denne artikel skal du have Python 3.5+

For at tjekke den python-version, du har i øjeblikket, skal du bare køre.

❯ python --version
Python 3.9.5 # My result

Hvis Python-versionen du får er 2.x, kan du bruge følgende kommando

python3 --version

Fortsætter med emnet, er hovedideen bag underprocesbiblioteket at være i stand til at interagere med OS ved at udføre de kommandoer, vi ønsker, direkte fra Python-fortolkeren.

Det betyder, at vi kan gøre, hvad vi vil, så længe vores OS tillader os (Og så længe du ikke fjerner dit rodfilsystem 😅).

  Indstilling af din Mac til produktivitet uden tredjepartsapps

Lad os se, hvordan du bruger det ved at oprette et simpelt script, der viser filerne i den aktuelle mappe.

Første delprocesansøgning

Lad os først oprette en fil list_dir.py. Dette vil være filen, hvor vi skal eksperimentere med at liste filer.

touch list_dir.py

Lad os nu åbne den fil og bruge følgende kode.

import subprocess 

subprocess.run('ls')

Først importerer vi underprocesmodulet, og bruger derefter funktionen run, som kører, den kommando, vi sender som et argument.

Denne funktion blev introduceret i Python 3.5, som en venlig genvej til underproces.Påben. Subprocess.run-funktionen giver os mulighed for at køre en kommando og vente på, at den er færdig, i modsætning til Popen, hvor vi har mulighed for at ringe til kommunikere senere.

Når vi taler om kodeoutput, er ls en UNIX-kommando, der viser filerne i det bibliotek, du er i. Derfor, hvis du kører denne kommando, får du en liste over de filer, der findes i den aktuelle mappe.

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

Bemærk: Vær opmærksom på, at hvis du er i Windows, skal du bruge forskellige kommandoer. For eksempel i stedet for at bruge “ls” kan du bruge “dir”

Dette kan virke for simpelt, og du har ret. Du vil have en fuld tilgang til al den kraft, som skallen giver dig. Så lad os lære, hvordan man sender argumenter til skallen med underprocessen.

For eksempel for også at liste de skjulte filer (dem der starter med en prik), og også liste alle filernes metadata, skriver vi følgende kode.

import subprocess

# subprocess.run('ls')  # Simple command

subprocess.run('ls -la', shell=True)

Vi kører denne kommando som en streng og bruger argumentskallen. Det betyder, at vi kalder en shell i starten af ​​udførelsen af ​​vores underproces, og kommandoargumentet fortolkes direkte af shellen.

Use shell=True har dog mange ulemper, og det værste er de mulige sikkerhedslækager. Du kan læse om dem i officiel dokumentation.

Den bedste måde at sende kommandoer til kørselsfunktionen på er at bruge en liste, hvor lst[0] er kommandoen til at kalde (ls i dette tilfælde) og lst[n] er argumenterne for den kommando.

Hvis vi gør det, vil vores kode se sådan ud.

import subprocess

# subprocess.run('ls')  # Simple command

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

subprocess.run(['ls', '-la'])

Hvis vi ønsker at gemme standardoutputtet fra en underproces i en variabel, kan vi gøre det ved at sætte argumentet capture_output til sand.

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'

For at få adgang til outputtet af en proces bruger vi instansattributten stdout.

I dette tilfælde ønsker vi at gemme outputtet som en streng i stedet for bytes, og vi kan gøre det ved at indstille tekstargumentet som sandt.

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, nu hvor vi kender det grundlæggende i underprocesbiblioteket, er det tid til at gå videre til nogle brugseksempler.

  En begyndervejledning til Google Web Stories [+4 Tools]

Anvendelse Eksempler på underprocesser i Python

I dette afsnit vil vi gennemgå nogle praktiske anvendelser af underprocesbiblioteket. Du kan tjekke dem alle i dette Github-depot.

Programkontrol

En af de vigtigste anvendelser af dette bibliotek er evnen til at lave enkle OS-operationer.

For eksempel et simpelt script, der kontrollerer, om et program er installeret. I Linux kan vi gøre dette med hvilken kommando.

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

Bemærk: I UNIX, når en kommando lykkes, er dens statuskode 0. Ellers gik noget galt under udførelsen

Da vi ikke bruger argumentet shell=True, kan vi tage brugerinputtet sikkert. Vi kan også kontrollere, om inputtet er et gyldigt program med et regex-mønster.

import subprocess

import re

programs = input('Separe the programs with a space: ').split()

secure_pattern = 'søn'

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

I dette tilfælde får vi programmerne fra brugeren og bruger et regex-udtryk, der bekræfter, at programstrengen kun indeholder bogstaver og cifre. Vi kontrollerer eksistensen af ​​hvert program med et for en loop.

Simpel Grep i Python

Din ven Tom har en liste over mønstre i en tekstfil og en anden stor fil, hvori han ønsker at få antallet af matches for hvert mønster. Han ville bruge timer på at køre grep-kommandoen for hvert mønster.

Heldigvis ved du, hvordan du løser dette problem med Python, og du vil hjælpe ham med at udføre denne opgave på få sekunder.

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

Ved at se på denne fil definerer vi to variabler, som er de filnavne, vi vil arbejde med. Så åbner vi filen, der indeholder alle mønstrene og itererer over dem. Dernæst kalder vi en underproces, der kører en grep-kommando med “-c”-flaget (betyder antal) og bestemmer resultatet af matchet med en betinget.

Hvis du kører denne fil (husk, at du kan downloade tekstfilerne fra Github repo)

Opsæt en virtualenv med underproces

En af de fedeste ting, du kan gøre med Python, er procesautomatisering. Denne form for script kan spare dig timers tid om ugen.

For eksempel vil vi oprette et opsætningsscript, der opretter et virtuelt miljø for os og forsøger at finde en requirement.txt-fil i den aktuelle mappe for at installere alle afhængigheder.

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

  11 Bedste Open Source Project Management Software [Self-hosted]

I dette tilfælde bruger vi flere processer og analyserer de data, vi har brug for i vores python-script. Vi bruger også stilib bibliotek, som giver os mulighed for at finde ud af, om filen requirements.txt eksisterer.

Hvis du kører python-filen, får du nogle nyttige beskeder om, hvad der sker med operativsystemet.

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

Bemærk, at vi får output fra installationsprocessen, fordi vi ikke omdirigerer standardoutputtet til en variabel.

Kør et andet programmeringssprog

Vi kan køre andre programmeringssprog med python og få output fra disse filer. Dette er muligt, fordi delprocesserne interagerer direkte med det operative system.

Lad os f.eks. lave et hello world-program i C++ og Java. For at udføre følgende fil, skal du installere C++ og Java kompilatorer.

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");  
    }  
}  

Jeg ved, at dette virker meget kode sammenlignet med en simpel Python one-liner, men dette er kun til testformål.

Vi skal lave et Python-script, der kører alle C++- og Java-filerne i en mappe. For at gøre dette vil vi først have en liste over filer afhængigt af filtypenavnet og glob giver os mulighed for nemt at gøre det!

from glob import glob

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

cpp_files = glob('*.cpp')

Derefter kan vi begynde at bruge underprocesser til at udføre hver type fil.

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)

Et lille trick er at bruge strengfunktionsstrimlen til at ændre outputtet og kun få det, vi har brug for.

Bemærk: Vær omhyggelig med at køre store Java- eller C++-filer, da vi indlæser deres output i hukommelsen, og det kan forårsage en hukommelseslækage.

Åbn eksterne programmer

Vi er i stand til at køre andre programmer blot ved at kalde deres binære placering gennem en underproces.

Lad os prøve det ved at åbne brave, min foretrukne webbrowser.

import subprocess

subprocess.run('brave')

Dette åbner en browserforekomst eller bare en anden fane, hvis du allerede har kørt browseren.

Som med ethvert andet program, der accepterer flag, kan vi bruge dem til at producere den ønskede adfærd.

import subprocess

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

For at opsummere

En delproces er en computerproces skabt af en anden proces. Vi kan tjekke de processer, vores computer kører, med værktøjer som htop og task manager.

Python har sit eget bibliotek til at arbejde med underprocesser. I øjeblikket giver kørselsfunktionen os en enkel grænseflade til at oprette og administrere underprocesser.

Vi kan oprette enhver form for applikation med dem, fordi vi interagerer direkte med OS.

Husk endelig, at den bedste måde at lære på er at skabe noget, du gerne vil bruge.