Kuidas kasutada Pythoni subprocess moodulit: Süsteemikäskude ja protsesside haldus

1. Mis on Pythoni subprocess moodul?

Ülevaade

Pythoni subprocess moodul on võimas tööriist süsteemikäskude ja väliste programmide käivitamiseks Pythonist. Selle mooduli abil saab hallata standardset sisendit/väljundit ja protsesse, mis lihtsustab Pythoni programmide ja väliste tööriistade integreerimist. See pakub turvalisemat ja paindlikumat protsessihaldust võrreldes vanemate meetoditega, nagu os.system() ja commands moodul.

Peamised kasutusviisid

  • Käsurea käskude käivitamine: Lihtsate süsteemikäskude täitmine.
  • Protsesside haldus: Väliste programmide käivitamine ja standardsete sisend/väljundvoogude suunamine.
  • Asünkroonne töötlus: Pikaajaliste või paralleelselt töötavate ülesannete käitlemine.

2. Põhiline kasutus: subprocess.run()

Põhiline kasutusviis

subprocess.run() funktsioon võimaldab süsteemikäsklusi lihtsalt Pythonis käivitada. Näiteks, et kuvada kataloogi faile:

import subprocess

result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)

See kood käivitab käsu ls -l, salvestab väljundi stdout muutujasse ja võimaldab Pythonis tulemust töödelda. capture_output=True salvestab väljundi ning text=True muudab tulemuse stringiks.

Veahaldus

Kui kasutad subprocess.run() ja käsk ebaõnnestub, saad veateate kätte stderr kaudu ning edukuse kontrollimiseks saab kasutada returncode muutujat.

result = subprocess.run(['ls', 'nonexistentfile'], capture_output=True, text=True)
if result.returncode != 0:
    print(f"Viga: {result.stderr}")

Selles näites, kui faili pole olemas, kuvatakse veateade standardveaväljundis.

侍エンジニア塾

3. Asünkroonne täitmine: subprocess.Popen()

Asünkroonne töötlus Popen abil

subprocess.run() on sünkroonne (programm ootab käsu lõppu), kuid subprocess.Popen() võimaldab protsessi käivitada asünkroonselt – muud tööd saavad paralleelselt jätkuda.

import subprocess

proc = subprocess.Popen(['sleep', '5'], stdout=subprocess.PIPE)
print("Protsess on käivitatud")
proc.wait()
print("Protsess on lõppenud")

See kood käivitab sleep 5 asünkroonselt, võimaldades muud tegevust samaaegselt.

Standard sisend/väljundi haldus

Popen võimaldab täpselt kontrollida standardset sisendit ja väljundit. Näiteks järgmine kood loeb andmed failist, töötleb need cat käsuga ja salvestab teise faili:

with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
    proc = subprocess.Popen(['cat'], stdin=infile, stdout=outfile)
    proc.wait()

Nii saab suunata sisendi/väljundi failidesse väliste käskude töötlemisel.

4. Kasutusnäide: automatiseeritud skriptid

Failide varundamine

Süsteemihalduse või korduvate ülesannete automatiseerimiseks on subprocess väga kasulik. Näiteks järgmine skript kopeerib failid automaatselt varunduskausta:

import subprocess

files_to_backup = ['file1.txt', 'file2.txt', 'file3.txt']
backup_dir = '/backup/directory/'

for file in files_to_backup:
    subprocess.run(['cp', file, backup_dir])

See kood kopeerib määratud failid varunduskataloogi, võimaldades regulaarset varundust automatiseerida.

Kasutus CI/CD torujuhtmes

subprocess on laialdaselt kasutusel pidevas integreerimises (CI) ja pidevas juurutamises (CD) – näiteks testskriptide automaatsel käivitamisel või juurutamisprotsessi osana. Näiteks saab automaatselt käivitada testid ja jätkata järgmise sammuga ainult õnnestumise korral.

侍エンジニア塾

5. Turvalisus ja parimad tavad

shell=True riskid

shell=True võimaldab käsklusi käivitada shelli kaudu, kuid sellega kaasnevad turvariskid. Eriti ohtlik on anda shellile väliseid kasutajasisendeid, kuna see võib viia shell-injection rünnakuteni. shell=False kasutamine vähendab seda riski.

import subprocess

# Soovitatav (turvaline) kasutusviis
subprocess.run(['ls', '-l'])

# shell=True (vajab ettevaatust)
subprocess.run('ls -l', shell=True)

Platvormiülene kasutus

Süsteemikäsud võivad erineda erinevatel operatsioonisüsteemidel. Näiteks võib kasutada Pythoni platform moodulit, et valida käsk OS-i alusel:

import platform
import subprocess

if platform.system() == "Windows":
    subprocess.run(['dir'], shell=True)
else:
    subprocess.run(['ls', '-l'])

6. Tõrkeotsing ja silumine

Levinumad vead ja lahendused

subprocess kasutamisel võib tihti esineda vigu, nagu failide puudumine või ligipääsuõigused. Sellised vead saab tuvastada stderr ja returncode abil.

Nõuanded silumiseks

check=True argument põhjustab käsu nurjumisel erindi, võimaldades probleemidest kiiresti teada saada. Standardväljundi ja veateadete logimine teeb silumise lihtsamaks.

import subprocess

try:
    result = subprocess.run(['ls', '-l'], check=True, capture_output=True, text=True)
    print(result.stdout)
except subprocess.CalledProcessError as e:
    print(f"Tekkis viga: {e}")

7. Asünkroonne töötlus ja koostöö asyncio-ga

Asünkroonne töötlus asyncio abil

asyncio võimaldab subprocess mooduliga paralleelselt mitut protsessi asünkroonselt töödelda. Järgnevas näites kasutatakse asyncio-d, et käivitada ls käsk ja töödelda tulemust:

import asyncio
import subprocess

async def run_command():
    proc = await asyncio.create_subprocess_exec('ls', '-l',
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)

    stdout, stderr = await proc.communicate()

    if stdout:
        print(f'[stdout]n{stdout.decode()}')
    if stderr:
        print(f'[stderr]n{stderr.decode()}')

asyncio.run(run_command())

See kood käivitab käsu asünkroonselt ja töötleb tulemused (stdout/stderr). asyncio võimaldab tõhusalt hallata paralleelseid ülesandeid.

侍エンジニア塾