Шта је подпроцес у Питхон-у? [5 Usage Examples]

Подпроцеси вам омогућавају интеракцију на потпуно новом нивоу са оперативним системом.

Наш рачунар стално покреће подпроцесе. У ствари, само читајући овај чланак, покрећете много процеса као што је менаџер мреже или сам интернет претраживач.

Добра ствар у вези са овим је да свака радња коју радимо на нашем рачунару укључује позивање подпроцеса. То остаје тачно чак и ако пишемо једноставну „здраво свет“ скрипту у Питхон-у.

Концепт подпроцеса може изгледати нејасно чак и ако већ неко време учите програмирање. Овај чланак ће детаљно размотрити главни концепт потпроцеса и начин на који се користи Питхон стандардна библиотека подпроцеса.

До краја овог водича ћете:

  • Разумети концепт подпроцеса
  • Научили сте основе Питхон библиотеке подпроцеса
  • Вежбали своје Питхон вештине на корисним примерима

Хајдемо у то

Концепт подпроцеса

Уопштено говорећи, подпроцес је а компјутерски процес створена другим процесом.

Подпроцес можемо замислити као стабло, у којем сваки родитељски процес иза себе има подпроцесе. Знам да ово може бити прилично збуњујуће, али хајде да то видимо са једноставном графиком.

Постоји неколико начина на које можемо да визуализујемо процес који се одвија на нашем рачунару. На пример, у УНИКС-у (Линук & МАЦ) имамо хтоп, који је интерактивни прегледник процеса.

Режим стабла је најкориснији алат за увид у покренуте подпроцесе. Можемо га активирати са Ф5.

Ако пажљиво погледамо одељак команди, можемо приметити структуру процеса који се покрећу на нашем рачунару.

Све почиње са /сбин/инит што је команда која покреће сваки процес на нашем рачунару. Од те тачке, можемо видети почетак других процеса као што су кфце4-сцреенсхотер и кфце4-терминал (што доводи до још више подпроцеса)

Ако погледамо Виндовс, имамо митски менаџер задатака што је корисно када се убијају они програми на нашој машини.

Сада имамо кристално јасан концепт. Хајде да видимо како можемо да имплементирамо подпроцесе у Питхон-у.

Подпроцеси у Питхон-у

Подпроцес у Питхон-у је задатак који питхон скрипта делегира оперативном систему (ОС).

Библиотека подпроцеса нам омогућава да извршавамо и управљамо подпроцесима директно из Питхон-а. То укључује рад са стандардним улазним стдин, стандардним излазним стдоут-ом и повратним кодовима.

Не морамо да га инсталирамо са ПИП-ом, пошто је део Питхон-а стандардна библиотека.

Стога можемо почети да користимо подпроцесе у Питхон-у само увозом модула.

import subprocess

# Using the module ....

Напомена: Да бисте пратили овај чланак, требало би да имате Питхон 3.5+

Да бисте проверили верзију Питхон-а коју тренутно имате, само покрените.

❯ python --version
Python 3.9.5 # My result

У случају да је Питхон верзија коју добијете 2.к можете користити следећу команду

python3 --version

Настављајући са темом, главна идеја иза библиотеке подпроцеса је да будемо у могућности да комуницирамо са ОС-ом извршавањем било које команде које желимо, директно из Питхон интерпретера.

То значи да можемо да радимо шта год желимо, све док нам наш ОС дозвољава (и све док не уклоните свој основни систем датотека 😅).

Хајде да видимо како да га користимо креирањем једноставне скрипте која наводи датотеке тренутног директоријума.

  Запамтите где сте паркирали и добијајте обавештења када ће ваш бројило ускоро истећи [iOS]

Прва апликација подпроцеса

Прво, направимо датотеку лист_дир.пи. Ово ће бити датотека у којој ћемо експериментисати са списком датотека.

touch list_dir.py

Сада отворимо ту датотеку и користимо следећи код.

import subprocess 

subprocess.run('ls')

Прво увозимо модул подпроцеса, а затим помоћу функције рун која се покреће, наредбу коју прослеђујемо као аргумент.

Ова функција је уведена у Питхон 3.5, као пријатељска пречица до подпроцес.Попен. Функција субпроцесс.рун нам омогућава да покренемо команду и сачекамо да се заврши, за разлику од Попен-а где имамо опцију да позовемо цоммуницате касније.

Говорећи о излазу кода, лс је УНИКС команда која наводи датотеке у директоријуму у којем се налазите. Стога, ако покренете ову команду, добићете листу датотека присутних у тренутном директоријуму.

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

Напомена: Узмите у обзир да ако сте у оперативном систему Виндовс, мораћете да користите различите команде. На пример, уместо коришћења „лс“ можете користити „дир“

Ово може изгледати превише једноставно и у праву сте. Желите да потпуно приступите свој моћи коју вам шкољка доноси. Дакле, хајде да научимо како да пренесемо аргументе у љуску са подпроцесом.

На пример, да бисмо навели и скривене датотеке (оне које почињу тачком), као и све метаподатке датотека, пишемо следећи код.

import subprocess

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

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

Покрећемо ову наредбу као стринг и користимо љуску аргумента. То значи да позивамо љуску на почетку извршавања нашег подпроцеса, а командни аргумент се тумачи директно од стране љуске.

Међутим, употреба схелл=Труе има многе недостатке, а најгоре су могућа сигурносна цурења. О њима можете прочитати у званична документација.

Најбољи начин за прослеђивање команди функцији рун је коришћење листе где је лст[0] је команда за позивање (лс у овом случају) и лст[n] су аргументи те команде.

Ако то урадимо, наш код ће изгледати овако.

import subprocess

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

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

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

Ако желимо да сачувамо стандардни излаз потпроцеса у променљивој, можемо то учинити тако што ћемо аргумент цаптуре_оутпут поставити на труе.

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'

Да бисмо приступили излазу процеса, користимо атрибут инстанце стдоут.

У овом случају желимо да сачувамо излаз као стринг, уместо бајтова и то можемо учинити тако што ћемо текстуални аргумент поставити као тачан.

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

Савршено, сада када знамо основе библиотеке подпроцеса, време је да пређемо на неке примере коришћења.

  Шта су еспортови и зашто их људи гледају?

Примери употребе подпроцеса у Питхон-у

У овом одељку ћемо прегледати неке практичне употребе библиотеке подпроцеса. Све их можете проверити у овоме Гитхуб спремиште.

Програм за проверу

Једна од главних употреба ове библиотеке је могућност једноставних операција ОС-а.

На пример, једноставна скрипта која проверава да ли је програм инсталиран. У Линуку то можемо да урадимо са командом вхицх.

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

Напомена: У УНИКС-у, када је команда успешна, њен статусни код је 0. У супротном, нешто је пошло наопако током извршавања

Пошто не користимо аргумент схелл=Труе, можемо безбедно да преузмемо кориснички унос. Такође, можемо да проверимо да ли је унос исправан програм са шаблоном регуларног израза.

import subprocess

import re

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

secure_pattern = 'Чет'

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

У овом случају, добијамо програме од корисника и користимо израз регуларног израза који потврђује да низ програма укључује само слова и цифре. Проверавамо постојање сваког програма помоћу фор петље.

Једноставан Греп у Питхон-у

Ваш пријатељ Том има листу шаблона у текстуалној датотеци и другу велику датотеку у којој жели да добије број подударања за сваки образац. Провео би сате извршавајући команду греп за сваки образац.

На срећу, знате како да решите овај проблем са Питхон-ом и помоћи ћете му да овај задатак обави за неколико секунди.

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

Гледајући ову датотеку, дефинишемо две варијабле које су имена датотека са којима желимо да радимо. Затим отварамо датотеку која садржи све обрасце и прелазимо преко њих. Затим позивамо подпроцес који покреће команду греп са заставицом „-ц“ (значи број) и одређујемо излаз подударања помоћу условног.

Ако покренете ову датотеку (запамтите да можете преузети текстуалне датотеке са Гитхуб репо)

Подесите виртуаленв са подпроцесом

Једна од најбољих ствари које можете да урадите са Питхоном је аутоматизација процеса. Ова врста скрипте може вам уштедети сате времена недељно.

На пример, креираћемо скрипту за подешавање која креира виртуелно окружење за нас и покушава да пронађе датотеку рекуирементс.ткт у тренутном директоријуму да би инсталирала све зависности.

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

  Како поправити гласан звучни сигнал на крају телефонских позива на Андроиду

У овом случају, користимо више процеса и анализирамо податке који су нам потребни у нашој питхон скрипти. Такође користимо патхлиб библиотека која нам омогућава да схватимо да ли постоји датотека рекуирементс.ткт.

Ако покренете Питхон датотеку, добићете неке корисне поруке о томе шта се дешава са ОС-ом.

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

Имајте на уму да излаз добијамо из процеса инсталације јер не преусмеравамо стандардни излаз на променљиву.

Покрените други програмски језик

Можемо покренути друге програмске језике са Питхон-ом и добити излаз из тих датотека. Ово је могуће јер су подпроцеси директно у интеракцији са оперативним системом.

На пример, хајде да направимо програм хелло ворлд у Ц++ и Јави. Да бисте извршили следећу датотеку, мораћете да инсталирате Ц++ и Јава компајлери.

хелловорлд.цпп

#include <iostream>

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

хелловорлд.јава

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

Знам да се чини да је ово много кода у поређењу са једноставним Питхон једноструким, али ово је само за потребе тестирања.

Направићемо Питхон скрипту која покреће све Ц++ и Јава датотеке у директоријуму. Да бисмо то урадили прво желимо да добијемо листу датотека у зависности од екстензије датотеке и глоб омогућава нам да то урадимо лако!

from glob import glob

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

cpp_files = glob('*.cpp')

Након тога, можемо почети да користимо подпроцесе за извршавање сваке врсте датотеке.

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)

Један мали трик је да користимо траку функције стринга да модификујемо излаз и добијемо само оно што нам је потребно.

Напомена: Пажљиво покрећете велике Јава или Ц++ датотеке јер учитавамо њихов излаз у меморију и то може довести до цурења меморије.

Отворите спољне програме

У могућности смо да покренемо друге програме само позивањем њихове бинарне локације кроз подпроцес.

Хајде да то испробамо тако што ћемо отворити браве, мој омиљени веб претраживач.

import subprocess

subprocess.run('brave')

Ово ће отворити инстанцу прегледача или само још једну картицу ако већ користите претраживач.

Као и са сваким другим програмом који прихвата ознаке, можемо их користити да произведемо жељено понашање.

import subprocess

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

Да сумирам

Подпроцес је рачунарски процес креиран другим процесом. Можемо да проверимо процесе које наш рачунар покреће помоћу алата као што су хтоп и менаџер задатака.

Питхон има сопствену библиотеку за рад са подпроцесима. Тренутно, функција рун нам даје једноставан интерфејс за креирање и управљање подпроцесима.

Са њима можемо да креирамо било коју врсту апликације јер смо у директној интеракцији са ОС-ом.

На крају, запамтите да је најбољи начин да научите да креирате нешто што бисте желели да користите.