Τι είναι μια υποδιεργασία στην Python; [5 Usage Examples]

Οι υποδιεργασίες σάς επιτρέπουν να αλληλεπιδράτε σε ένα εντελώς νέο επίπεδο με το λειτουργικό σύστημα.

Ο υπολογιστής μας εκτελεί υποδιεργασίες όλη την ώρα. Στην πραγματικότητα, διαβάζοντας μόνο αυτό το άρθρο, εκτελείτε πολλές διαδικασίες όπως ένας διαχειριστής δικτύου ή το ίδιο το πρόγραμμα περιήγησης στο Διαδίκτυο.

Το ωραίο με αυτό είναι ότι οποιαδήποτε ενέργεια κάνουμε στον υπολογιστή μας περιλαμβάνει την επίκληση μιας υποδιεργασίας. Αυτό παραμένει αληθινό ακόμα κι αν γράφουμε ένα απλό σενάριο “hello world” σε python.

Η έννοια της υποδιαδικασίας μπορεί να φαίνεται ασαφής ακόμα κι αν μαθαίνετε προγραμματισμό για λίγο. Αυτό το άρθρο θα ρίξει μια βαθιά ματιά στην κύρια έννοια της υποδιαδικασίας και πώς να χρησιμοποιήσετε την Python τυπική βιβλιοθήκη υποδιεργασίας.

Μέχρι το τέλος αυτού του σεμιναρίου, θα:

  • Κατανοήστε την έννοια της υποδιεργασίας
  • Έχετε μάθει τα βασικά της βιβλιοθήκης υποδιαδικασιών Python
  • Εξασκήστε τις δεξιότητές σας στο Python με χρήσιμα παραδείγματα

Ας μπούμε σε αυτό

Η έννοια της υποδιαδικασίας

Σε γενικές γραμμές, μια υποδιεργασία είναι α διαδικασία υπολογιστή που δημιουργήθηκε από άλλη διαδικασία.

Μπορούμε να σκεφτούμε μια υποδιεργασία ως ένα δέντρο, στο οποίο κάθε γονική διεργασία έχει θυγατρικές διεργασίες που τρέχουν πίσω της. Ξέρω ότι αυτό μπορεί να είναι αρκετά μπερδεμένο, αλλά ας το δούμε με ένα απλό γραφικό.

Υπάρχουν διάφοροι τρόποι με τους οποίους μπορούμε να οπτικοποιήσουμε τη διαδικασία που εκτελείται στον υπολογιστή μας. Για παράδειγμα, στο UNIX (Linux & MAC) έχουμε htop, που είναι ένα διαδραστικό πρόγραμμα προβολής διεργασιών.

Η λειτουργία δέντρου είναι το πιο χρήσιμο εργαλείο για να ρίξετε μια ματιά στις υποδιεργασίες που εκτελούνται. Μπορούμε να το ενεργοποιήσουμε με το F5.

Αν κοιτάξουμε προσεκτικά την ενότητα εντολών, μπορούμε να παρατηρήσουμε τη δομή των διεργασιών που εκτελούνται στον υπολογιστή μας.

Όλα ξεκινούν με /sbin/init που είναι η εντολή που ξεκινά κάθε διαδικασία στον υπολογιστή μας. Από εκείνο το σημείο, μπορούμε να δούμε την αρχή άλλων διεργασιών όπως το xfce4-screenshoter και το xfce4-terminal (που οδηγεί σε ακόμη μεγαλύτερη υποδιεργασία)

Ρίχνοντας μια ματιά στα Windows, έχουμε το μυθικό διαχειριστής εργασιών κάτι που είναι χρήσιμο όταν σκοτώνουμε αυτά τα προγράμματα που συντρίβουν στο μηχάνημά μας.

Τώρα έχουμε μια πεντακάθαρη ιδέα. Ας δούμε πώς μπορούμε να υλοποιήσουμε υποδιεργασίες στην Python.

Υποδιεργασίες στην Python

Μια υποδιεργασία στην Python είναι μια εργασία που ένα σενάριο python αναθέτει στο λειτουργικό σύστημα (OS).

Η βιβλιοθήκη υποδιαδικασιών μας επιτρέπει να εκτελούμε και να διαχειριζόμαστε υποδιεργασίες απευθείας από την Python. Αυτό περιλαμβάνει εργασία με την τυπική είσοδο stdin, την τυπική έξοδο stdout και τους κωδικούς επιστροφής.

Δεν χρειάζεται να το εγκαταστήσουμε με PIP, αφού είναι μέρος της Python τυπική βιβλιοθήκη.

Επομένως, μπορούμε να αρχίσουμε να χρησιμοποιούμε υποδιεργασίες στην python απλώς εισάγοντας το module.

import subprocess

# Using the module ....

Σημείωση: Για να ακολουθήσετε αυτό το άρθρο θα πρέπει να έχετε Python 3.5 +

Για να ελέγξετε την έκδοση python που έχετε αυτήν τη στιγμή, απλώς εκτελέστε.

❯ python --version
Python 3.9.5 # My result

Σε περίπτωση που η έκδοση Python που λαμβάνετε είναι 2.x, μπορείτε να χρησιμοποιήσετε την παρακάτω εντολή

python3 --version

Συνεχίζοντας με το θέμα, η κύρια ιδέα πίσω από τη βιβλιοθήκη υποδιαδικασιών είναι να μπορούμε να αλληλεπιδράσουμε με το λειτουργικό σύστημα εκτελώντας όποιες εντολές θέλουμε, απευθείας από τον διερμηνέα Python.

  10 καλύτερος εξοπλισμός ροής και εξοπλισμός για επαγγελματικά παιχνίδια

Αυτό σημαίνει ότι μπορούμε να κάνουμε ό,τι θέλουμε, εφόσον μας το επιτρέπει το λειτουργικό μας σύστημα (Και αρκεί να μην καταργήσετε το root σύστημα αρχείων σας 😅).

Ας δούμε πώς να το χρησιμοποιήσετε δημιουργώντας ένα απλό σενάριο που παραθέτει τα αρχεία του τρέχοντος καταλόγου.

Πρώτη εφαρμογή υποδιεργασίας

Αρχικά, ας δημιουργήσουμε ένα αρχείο list_dir.py. Αυτό θα είναι το αρχείο στο οποίο θα πειραματιστούμε με την καταχώριση αρχείων.

touch list_dir.py

Τώρα ας ανοίξουμε αυτό το αρχείο και ας χρησιμοποιήσουμε τον παρακάτω κώδικα.

import subprocess 

subprocess.run('ls')

Πρώτα, εισάγουμε τη λειτουργική μονάδα υποδιεργασίας και, στη συνέχεια, χρησιμοποιώντας τη συνάρτηση εκτέλεσης που εκτελείται, την εντολή που περνάμε ως όρισμα.

Αυτή η λειτουργία εισήχθη στην Python 3.5, ως μια φιλική συντόμευση προς υποδιεργασία.Άνοιγμα. Η συνάρτηση subprocess.run μας επιτρέπει να εκτελέσουμε μια εντολή και να περιμένουμε να τελειώσει, σε αντίθεση με το Popen όπου έχουμε την επιλογή να καλέσουμε επικοινωνία αργότερα.

Μιλώντας για την έξοδο κώδικα, το ls είναι μια εντολή UNIX που παραθέτει τα αρχεία του καταλόγου στον οποίο βρίσκεστε. Επομένως, εάν εκτελέσετε αυτήν την εντολή, θα λάβετε μια λίστα με τα αρχεία που υπάρχουν στον τρέχοντα κατάλογο.

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

Σημείωση: Λάβετε υπόψη ότι εάν είστε σε Windows, θα χρειαστεί να χρησιμοποιήσετε διαφορετικές εντολές. Για παράδειγμα, αντί να χρησιμοποιήσετε το “ls” μπορείτε να χρησιμοποιήσετε το “dir”

Αυτό μπορεί να φαίνεται πολύ απλό και έχετε δίκιο. Θέλετε να προσεγγίσετε πλήρως όλη τη δύναμη που σας φέρνει το κέλυφος. Ας μάθουμε λοιπόν πώς να περνάμε ορίσματα στο κέλυφος με υποδιεργασία.

Για παράδειγμα, για να παραθέσουμε επίσης τα κρυφά αρχεία (Αυτά που ξεκινούν με τελεία), καθώς και όλα τα μεταδεδομένα των αρχείων, γράφουμε τον ακόλουθο κώδικα.

import subprocess

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

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

Εκτελούμε αυτήν την εντολή ως συμβολοσειρά και χρησιμοποιούμε το φλοιό ορισμάτων. Αυτό σημαίνει ότι καλούμε ένα φλοιό στην αρχή της εκτέλεσης της υποδιαδικασίας μας και το όρισμα εντολής ερμηνεύεται απευθείας από το φλοιό.

Ωστόσο, η χρήση shell=True έχει πολλά μειονεκτήματα και τα χειρότερα είναι οι πιθανές διαρροές ασφαλείας. Μπορείτε να διαβάσετε για αυτούς στο επίσημη τεκμηρίωση.

Ο καλύτερος τρόπος για να περάσετε εντολές στη συνάρτηση εκτέλεσης είναι να χρησιμοποιήσετε μια λίστα όπου lst[0] είναι η εντολή για κλήση (ls σε αυτή την περίπτωση) και lst[n] είναι τα επιχειρήματα αυτής της εντολής.

Αν το κάνουμε αυτό, ο κώδικάς μας θα μοιάζει με αυτό.

import subprocess

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

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

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

Εάν θέλουμε να αποθηκεύσουμε την τυπική έξοδο μιας υποδιεργασίας σε μια μεταβλητή, μπορούμε να το κάνουμε ορίζοντας το όρισμα capture_output σε true.

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'

Για να αποκτήσουμε πρόσβαση στην έξοδο μιας διεργασίας, χρησιμοποιούμε το χαρακτηριστικό παράδειγμα stdout.

Σε αυτήν την περίπτωση, θέλουμε να αποθηκεύσουμε την έξοδο ως συμβολοσειρά, αντί για byte και μπορούμε να το κάνουμε ορίζοντας το όρισμα κειμένου ως αληθές.

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

Τέλεια, τώρα που γνωρίζουμε τα βασικά της βιβλιοθήκης υποδιαδικασιών, ήρθε η ώρα να προχωρήσουμε σε μερικά παραδείγματα χρήσης.

  Πώς να ενημερώσετε το iPad σας στην πιο πρόσφατη έκδοση του iPadOS

Παραδείγματα χρήσης υποδιεργασίας στην Python

Σε αυτήν την ενότητα, θα εξετάσουμε ορισμένες πρακτικές χρήσεις της βιβλιοθήκης υποδιαδικασιών. Μπορείτε να τα ελέγξετε όλα σε αυτό Αποθετήριο Github.

Έλεγχος προγράμματος

Μία από τις κύριες χρήσεις αυτής της βιβλιοθήκης είναι η δυνατότητα πραγματοποίησης απλών λειτουργιών του λειτουργικού συστήματος.

Για παράδειγμα, ένα απλό σενάριο που ελέγχει εάν ένα πρόγραμμα είναι εγκατεστημένο. Στο Linux, μπορούμε να το κάνουμε αυτό με την εντολή που.

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

Σημείωση: Στο UNIX, όταν μια εντολή είναι επιτυχής, ο κωδικός της κατάστασης είναι 0. Διαφορετικά, κάτι πήγε στραβά κατά την εκτέλεση

Εφόσον δεν χρησιμοποιούμε το όρισμα shell=True, μπορούμε να πάρουμε με ασφάλεια την είσοδο του χρήστη. Επίσης, μπορούμε να ελέγξουμε αν η είσοδος είναι έγκυρο πρόγραμμα με regex μοτίβο.

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

Σε αυτήν την περίπτωση, λαμβάνουμε τα προγράμματα από τον χρήστη και χρησιμοποιούμε μια έκφραση regex που πιστοποιεί ότι η συμβολοσειρά του προγράμματος περιλαμβάνει μόνο γράμματα και ψηφία. Ελέγχουμε την ύπαρξη κάθε προγράμματος με ένα βρόχο for.

Απλό Grep στην Python

Ο φίλος σας Tom έχει μια λίστα με μοτίβα σε ένα αρχείο κειμένου και ένα άλλο μεγάλο αρχείο στο οποίο θέλει να πάρει τον αριθμό των αντιστοιχιών για κάθε μοτίβο. Θα περνούσε ώρες τρέχοντας την εντολή grep για κάθε μοτίβο.

Ευτυχώς, ξέρετε πώς να λύσετε αυτό το πρόβλημα με την Python και θα τον βοηθήσετε να ολοκληρώσει αυτήν την εργασία σε λίγα δευτερόλεπτα.

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

Ρίχνοντας μια ματιά σε αυτό το αρχείο, ορίζουμε δύο μεταβλητές που είναι τα ονόματα αρχείων με τα οποία θέλουμε να εργαστούμε. Στη συνέχεια ανοίγουμε το αρχείο που περιέχει όλα τα μοτίβα και επαναλαμβάνουμε πάνω τους. Στη συνέχεια, καλούμε μια υποδιεργασία που εκτελεί μια εντολή grep με τη σημαία “-c” (σημαίνει μέτρηση) και προσδιορίζουμε την έξοδο της αντιστοίχισης με μια υπό όρους.

Εάν εκτελείτε αυτό το αρχείο (θυμηθείτε ότι μπορείτε να κάνετε λήψη των αρχείων κειμένου από το Αποθετήριο Github)

Ρυθμίστε ένα virtualenv με υποδιεργασία

Ένα από τα πιο ωραία πράγματα που μπορείτε να κάνετε με την Python είναι η αυτοματοποίηση διαδικασιών. Αυτό το είδος σεναρίου μπορεί να σας εξοικονομήσει ώρες χρόνου την εβδομάδα.

Για παράδειγμα, θα δημιουργήσουμε ένα σενάριο εγκατάστασης που δημιουργεί ένα εικονικό περιβάλλον για εμάς και προσπαθεί να βρει ένα αρχείο requires.txt στον τρέχοντα κατάλογο για να εγκαταστήσει όλες τις εξαρτήσεις.

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

  Πώς να ηχογραφήσετε κλήσεις Skype με τη νέα δυνατότητα εγγενούς εγγραφής

Σε αυτήν την περίπτωση, χρησιμοποιούμε πολλαπλές διεργασίες και αναλύουμε τα δεδομένα που χρειαζόμαστε στο σενάριο python μας. Χρησιμοποιούμε επίσης το pathlib βιβλιοθήκη που μας επιτρέπει να το καταλάβουμε εάν υπάρχει το αρχείο απαιτήσεις.txt.

Εάν εκτελέσετε το αρχείο python, θα λάβετε μερικά χρήσιμα μηνύματα για το τι συμβαίνει με το λειτουργικό σύστημα.

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

Σημειώστε ότι λαμβάνουμε το αποτέλεσμα από τη διαδικασία εγκατάστασης επειδή δεν ανακατευθύνουμε την τυπική έξοδο σε μια μεταβλητή.

Εκτελέστε μια άλλη γλώσσα προγραμματισμού

Μπορούμε να τρέξουμε άλλες γλώσσες προγραμματισμού με την python και να πάρουμε την έξοδο από αυτά τα αρχεία. Αυτό είναι δυνατό επειδή οι υποδιεργασίες αλληλεπιδρούν άμεσα με το λειτουργικό σύστημα.

Για παράδειγμα, ας δημιουργήσουμε ένα πρόγραμμα hello world σε C++ και Java. Για να εκτελέσετε το ακόλουθο αρχείο, θα πρέπει να το εγκαταστήσετε C++ και Ιάβα μεταγλωττιστές.

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

Ξέρω ότι φαίνεται πολύς κώδικας σε σύγκριση με ένα απλό Python one-liner, αλλά αυτό είναι μόνο για δοκιμαστικούς σκοπούς.

Θα δημιουργήσουμε ένα σενάριο Python που εκτελεί όλα τα αρχεία C++ και 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)

Ένα μικρό κόλπο είναι να χρησιμοποιήσουμε τη λωρίδα συνάρτησης συμβολοσειράς για να τροποποιήσουμε την έξοδο και να πάρουμε μόνο αυτό που χρειαζόμαστε.

Σημείωση: Προσέξτε να εκτελείτε μεγάλα αρχεία Java ή C++, καθώς φορτώνουμε την έξοδο τους στη μνήμη και αυτό μπορεί να προκαλέσει διαρροή μνήμης.

Ανοίξτε εξωτερικά προγράμματα

Μπορούμε να εκτελέσουμε άλλα προγράμματα απλώς καλώντας τη θέση τους στα δυαδικά αρχεία μέσω μιας υποδιεργασίας.

Ας το δοκιμάσουμε ανοίγοντας το brave, το προτιμώμενο πρόγραμμα περιήγησης ιστού.

import subprocess

subprocess.run('brave')

Αυτό θα ανοίξει μια παρουσία του προγράμματος περιήγησης ή απλώς μια άλλη καρτέλα, εάν έχετε ήδη εκτελέσει το πρόγραμμα περιήγησης.

Όπως με κάθε άλλο πρόγραμμα που δέχεται σημαίες, μπορούμε να τα χρησιμοποιήσουμε για να δημιουργήσουμε την επιθυμητή συμπεριφορά.

import subprocess

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

Εν κατακλείδι

Μια υποδιεργασία είναι μια διεργασία υπολογιστή που δημιουργείται από μια άλλη διεργασία. Μπορούμε να ελέγξουμε τις διαδικασίες που εκτελεί ο υπολογιστής μας με εργαλεία όπως το htop και το Task Manager.

Η Python έχει τη δική της βιβλιοθήκη για να δουλεύει με υποδιεργασίες. Επί του παρόντος, η συνάρτηση εκτέλεσης μας δίνει μια απλή διεπαφή για τη δημιουργία και τη διαχείριση υποδιαδικασιών.

Μπορούμε να δημιουργήσουμε κάθε είδους εφαρμογή με αυτά επειδή αλληλεπιδρούμε απευθείας με το λειτουργικό σύστημα.

Τέλος, να θυμάστε ότι ο καλύτερος τρόπος για να μάθετε είναι να δημιουργήσετε κάτι που θα θέλατε να χρησιμοποιήσετε.