Mi az a részfolyamat a Pythonban? [5 Usage Examples]

Az alfolyamatok segítségével teljesen új szinten léphet kapcsolatba az operációs rendszerrel.

Számítógépünk folyamatosan alfolyamatokat futtat. Valójában a cikk elolvasásával számos folyamatot futtat, például egy hálózatkezelőt vagy magát az internetböngészőt.

Ebben az a klassz, hogy a számítógépünkön végrehajtott bármely művelet magában foglalja egy részfolyamat meghívását. Ez akkor is igaz, ha egy egyszerű „hello world” szkriptet írunk pythonban.

Az alfolyamat fogalma homályosnak tűnhet még akkor is, ha már egy ideje programozást tanul. Ez a cikk alaposan áttekinti az alfolyamat fő koncepcióját és a Python használatát alfolyamat szabványos könyvtár.

Ennek az oktatóanyagnak a végére a következőket fogja tenni:

  • Értse a részfolyamat fogalmát
  • Megtanulta a Python alfolyamat-könyvtár alapjait
  • Hasznos példákkal gyakoroltad Python-készségeidet

Menjünk bele

A részfolyamat fogalma

Nagy vonalakban egy részfolyamat a számítógépes folyamat más folyamat hozta létre.

Az alfolyamatokat egy fának tekinthetjük, amelyben minden szülőfolyamat mögött gyermekfolyamatok futnak. Tudom, hogy ez elég zavaró lehet, de nézzük meg egy egyszerű grafikával.

A számítógépünkön futó folyamatot többféleképpen is elképzelhetjük. Például UNIX-ban (Linux és MAC) van htop, amely egy interaktív folyamatnézegető.

A fa mód a leghasznosabb eszköz a futó részfolyamatok áttekintésére. Az F5-tel aktiválhatjuk.

Ha alaposan megnézzük a parancsrészt, észrevehetjük a számítógépünkön futó folyamatok felépítését.

Minden azzal kezdődik /sbin/init amely az egyes folyamatokat elindító parancs a számítógépünkön. Ettől kezdve láthatjuk más folyamatok kezdetét, mint például az xfce4-screenshoter és az xfce4-terminál (ami még több részfolyamathoz vezet)

Ha egy pillantást vetünk a Windowsra, megvan a mitikus feladatkezelő ami hasznos a gépünkön lévő összeomló programok megölésekor.

Most kristálytiszta koncepciónk van. Nézzük meg, hogyan valósíthatunk meg részfolyamatokat Pythonban.

Alfolyamatok Pythonban

A Python alfolyamata egy olyan feladat, amelyet egy python-szkript delegál az operációs rendszerre (OS).

Az alfolyamat-könyvtár lehetővé teszi részfolyamatok végrehajtását és kezelését közvetlenül a Pythonból. Ez magában foglalja a szabványos bemeneti stdin, szabványos kimeneti stdout és visszatérési kódok használatát.

Nem kell PIP-vel telepítenünk, mivel a Python része szabványos könyvtár.

Ezért a pythonban elkezdhetjük használni az alfolyamatokat a modul importálásával.

import subprocess

# Using the module ....

Megjegyzés: A cikk követéséhez Python 3.5+ verzióra van szükség

A jelenleg rendelkezésre álló Python verzió ellenőrzéséhez egyszerűen futtassa.

❯ python --version
Python 3.9.5 # My result

Ha a kapott Python verzió 2.x, akkor a következő parancsot használhatja

python3 --version

Folytatva a témát, az alfolyamat-könyvtár mögött meghúzódó fő gondolat az, hogy képes legyen interakcióba lépni az operációs rendszerrel bármely kívánt parancs végrehajtásával, közvetlenül a Python interpreterből.

Ez azt jelenti, hogy bármit megtehetünk, ameddig az operációs rendszerünk lehetővé teszi (és mindaddig, amíg nem távolítja el a gyökér fájlrendszerét 😅).

Nézzük meg, hogyan kell használni egy egyszerű szkript létrehozásával, amely felsorolja az aktuális könyvtár fájljait.

Első részfolyamat alkalmazás

Először hozzunk létre egy list_dir.py fájlt. Ez lesz az a fájl, ahol kísérletezni fogunk a fájlok felsorolásával.

touch list_dir.py

Most nyissuk meg a fájlt, és használjuk a következő kódot.

import subprocess 

subprocess.run('ls')

Először importáljuk az alfolyamat modult, majd a futtatott függvény segítségével az argumentumként átadott parancsot.

  PostgreSQL adatbázis-kiszolgáló beállítása Webmin segítségével az Ubuntu szerveren

Ezt a funkciót a Python 3.5-ben vezették be, barátságos parancsikonként részfolyamat.Popen. A subprocess.run függvény lehetővé teszi, hogy parancsokat futtassunk, és várjuk meg a befejezést, ellentétben a Popennel, ahol lehetőségünk van a kommunikációt később hívni.

Ha a kódkimenetről beszélünk, az ls egy UNIX-parancs, amely kilistázza annak a könyvtárnak a fájljait, amelyben éppen tartózkodik. Ezért ha ezt a parancsot futtatja, megjelenik az aktuális könyvtárban található fájlok listája.

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

Megjegyzés: Vegye figyelembe, hogy ha Windows rendszert használ, különböző parancsokat kell használnia. Például az „ls” helyett használhatja a „dir” kifejezést.

Ez túl egyszerűnek tűnhet, és igazad van. Teljesen meg akarja közelíteni mindazt az erőt, amelyet a shell nyújt Önnek. Tehát tanuljuk meg, hogyan adjunk át argumentumokat a héjnak az alfolyamatokkal.

Például a rejtett fájlok listázásához (Amik ponttal kezdődnek), valamint a fájlok összes metaadatát is kiírjuk a következő kódot.

import subprocess

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

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

Ezt a parancsot karakterláncként futtatjuk, és az argumentumhéjat használjuk. Ez azt jelenti, hogy az alfolyamat végrehajtásának elején egy shell-t hívunk meg, és a parancs argumentumát közvetlenül a shell értelmezi.

A use shell=True-nak azonban számos hátránya van, és a legrosszabb az esetleges biztonsági szivárgás. Olvashat róluk a hivatalos dokumentáció.

A parancsok átadásának legjobb módja a futási függvénynek egy olyan lista használata, ahol az lst[0] a hívás parancsa (ebben az esetben ls) és lst[n] ezek a parancs érvei.

Ha így teszünk, a kódunk így fog kinézni.

import subprocess

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

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

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

Ha egy alfolyamat szabványos kimenetét szeretnénk egy változóban tárolni, akkor azt úgy tehetjük meg, hogy a capture_output argumentumot igazra állítjuk.

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'

A folyamat kimenetének eléréséhez az stdout példányattribútumot használjuk.

Ebben az esetben a kimenetet bájtok helyett karakterláncként szeretnénk tárolni, és ezt úgy tehetjük meg, hogy a szöveges argumentumot igazra állítjuk.

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

Tökéletes, most, hogy ismerjük az alfolyamat-könyvtár alapjait, ideje áttérni néhány használati példára.

  Az eharmónia-előfizetés lemondása

Használati példák a Python alfolyamataira

Ebben a részben az alfolyamat-könyvtár néhány gyakorlati felhasználását tekintjük át. Ebben mindegyiket ellenőrizheti Github adattár.

Programellenőrző

Ennek a könyvtárnak az egyik fő felhasználási területe az egyszerű operációs rendszer műveletek elvégzésének képessége.

Például egy egyszerű szkript, amely ellenőrzi, hogy egy program telepítve van-e. Linuxban ezt a which paranccsal tehetjük meg.

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

Megjegyzés: UNIX-ban, ha egy parancs sikeres, annak állapotkódja 0. Ellenkező esetben valami hiba történt a végrehajtás során

Mivel nem a shell=True argumentumot használjuk, biztonságosan tudjuk kezelni a felhasználói bevitelt. Azt is ellenőrizhetjük, hogy a bemenet érvényes program-e regex mintával.

import subprocess

import re

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

secure_pattern = 'ked'

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

Ebben az esetben a programokat a felhasználótól kapjuk, és egy regex kifejezést használunk, amely tanúsítja, hogy a programkarakterlánc csak betűket és számjegyeket tartalmaz. Minden egyes program létezését a for ciklussal ellenőrizzük.

Egyszerű Grep Pythonban

A barátodnak, Tomnak van egy listája a mintákról egy szövegfájlban, és egy másik nagy fájl, amelyben meg akarja szerezni az egyes mintákhoz tartozó egyezések számát. Órákon át futtatta a grep parancsot minden mintához.

Szerencsére Ön tudja, hogyan oldja meg ezt a problémát Pythonnal, és néhány másodperc alatt segít neki a feladat elvégzésében.

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

Ha megnézzük ezt a fájlt, két változót határozunk meg, amelyek a fájlnevek, amelyekkel dolgozni szeretnénk. Ezután megnyitjuk az összes mintát tartalmazó fájlt, és iterálunk rajtuk. Ezután meghívunk egy alfolyamatot, amely egy grep parancsot futtat a „-c” jelzővel (számítást jelent), és meghatározzuk az egyezés kimenetét egy feltétellel.

Ha futtatja ezt a fájlt (ne feledje, hogy letöltheti a szöveges fájlokat a Github repo)

Állítson be egy virtualenv-t alfolyamattal

Az egyik legmenőbb dolog, amit Pythonnal tehet, a folyamatautomatizálás. Ez a fajta szkript hetente órákat takaríthat meg.

Például létrehozunk egy telepítő szkriptet, amely létrehoz egy virtuális környezetet számunkra, és megpróbálja megtalálni a követelmények.txt fájlt az aktuális könyvtárban, hogy telepítse az összes függőséget.

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

  A Mac OS Monterey futtatása Ubuntun

Ebben az esetben több folyamatot használunk, és elemezzük a szükséges adatokat a python-szkriptünkben. Mi is használjuk a pathlib könyvtár, amely lehetővé teszi számunkra, hogy kitaláljuk, ha a követelmények.txt fájl létezik.

Ha futtatja a python fájlt, hasznos üzeneteket fog kapni arról, hogy mi történik az operációs rendszerrel.

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

Vegye figyelembe, hogy a telepítési folyamat kimenetét kapjuk, mert nem irányítjuk át a szabványos kimenetet egy változóra.

Futtasson másik programozási nyelvet

Más programozási nyelveket is futtathatunk a python segítségével, és lekérhetjük a kimenetet ezekből a fájlokból. Ez azért lehetséges, mert az alfolyamatok közvetlenül kölcsönhatásba lépnek az operációs rendszerrel.

Például hozzunk létre egy hello world programot C++ és Java nyelven. A következő fájl végrehajtásához telepítenie kell C++ és Jáva fordítók.

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

Tudom, hogy ez sok kódnak tűnik egy egyszerű Python egysoroshoz képest, de ez csak tesztelési célokat szolgál.

Létre fogunk hozni egy Python szkriptet, amely az összes C++ és Java fájlt futtatja egy könyvtárban. Ehhez először szeretnénk lekérni a fájlok listáját a fájlkiterjesztéstől függően, és glob lehetővé teszi számunkra, hogy könnyen megcsináljuk!

from glob import glob

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

cpp_files = glob('*.cpp')

Ezt követően elkezdhetjük alfolyamatokat használni az egyes fájltípusok végrehajtásához.

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)

Egy kis trükk az, hogy a karakterlánc függvénysávot használjuk a kimenet módosítására, és csak azt kapjuk meg, amire szükségünk van.

Megjegyzés: Legyen óvatos a nagy Java vagy C++ fájlok futtatásakor, mivel a kimenetüket a memóriába töltjük, és ez memóriaszivárgást okozhat.

Nyissa meg a külső programokat

Más programokat csak úgy tudunk futtatni, hogy egy alfolyamaton keresztül meghívjuk a bináris fájljuk helyét.

Próbáljuk ki a brave, az általam preferált webböngésző megnyitásával.

import subprocess

subprocess.run('brave')

Ez megnyit egy böngészőpéldányt, vagy csak egy másik lapot, ha már fut a böngésző.

Mint minden más program, amely elfogadja a jelzőket, használhatjuk őket a kívánt viselkedés létrehozására.

import subprocess

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

Összefoglalva

Az alfolyamat egy másik folyamat által létrehozott számítógépes folyamat. A számítógépünkön futó folyamatokat olyan eszközökkel ellenőrizhetjük, mint a htop és a feladatkezelő.

A Pythonnak saját könyvtára van az alfolyamatokkal való együttműködéshez. Jelenleg a futtatás funkció egyszerű felületet biztosít részfolyamatok létrehozásához és kezeléséhez.

Bármilyen alkalmazást létrehozhatunk velük, mivel közvetlenül kommunikálunk az operációs rendszerrel.

Végül ne feledd, hogy a tanulás legjobb módja az, ha létrehozol valamit, amit használni szeretnél.