Om du er en Linux-bruker, er det stor sannsynlighet for at du setter pris på kraften i skallkommandoer.
Dersom du i tillegg jobber med Python, har du kanskje allerede utforsket muligheten for å automatisere oppgaver. Dette er en effektiv måte å spare tid på. Det er også mulig å bruke bash-skript for automatisering.
Python er et svært nyttig verktøy for å skrive skript, og mange anser det som et bedre alternativ enn bash. Python-skript er også enklere å administrere, spesielt når de blir mer komplekse. Bash-skript kan raskt bli vanskelige å vedlikeholde etter hvert som de vokser i størrelse og omfang.
Men hva om du allerede har bash-skript som du ønsker å bruke i Python?
Finnes det en måte å kjøre disse bash-kommandoene og skriptene direkte fra Python?
Svaret er ja. Python har en innebygd modul som heter `subprocess`. Denne modulen gir deg muligheten til å utføre både kommandoer og skript direkte fra dine Python-programmer. La oss se nærmere på hvordan du kan bruke dette til å kjøre bash-kommandoer og skript fra Python.
Utføre Bash-kommandoer
Som nevnt, er `subprocess`-modulen nøkkelen til å utføre bash-kommandoer og skript. Modulen tilbyr ulike metoder og klasser for å oppnå dette.
Spesielt to viktige elementer fra `subprocess`-modulen er verdt å kjenne: `run` og `Popen`. Disse to hjelper deg å utføre bash-kommandoer i dine Python-skript. La oss se nærmere på hver av dem.
subprocess.run()
Metoden `subprocess.run()` tar en liste av strenger som et posisjonsargument. Denne listen er obligatorisk og inneholder selve bash-kommandoen, i tillegg til eventuelle argumenter. Det første elementet i listen er kommandonavnet, mens de resterende elementene er argumenter til kommandoen.
La oss illustrere dette med et enkelt eksempel.
import subprocess subprocess.run(["ls"])
Skriptet ovenfor vil vise alle elementene i gjeldende arbeidsmappe der skriptet befinner seg. I dette eksemplet har vi ingen argumenter for kommandoen, kun selve kommandoen `ls`. Vi kan imidlertid legge til flere argumenter til `ls`-kommandoen, som for eksempel `-l`, `-a` eller `-la`.
Her er et eksempel med kommandoargumenter:
import subprocess subprocess.run(["ls", "-la"])
Denne kommandoen vil vise alle filer og mapper, inkludert skjulte filer, sammen med tilhørende rettigheter. Argumentet `-la` gir ekstra informasjon og viser skjulte filer og mapper.
Det kan fort oppstå feil når man skriver kommandoer. Disse feilene kan hoper seg opp. Hvis du ønsker å fange opp disse feilene og bruke dem senere, kan du bruke nøkkelordargumentet `stderr`.
Her er et eksempel:
import subprocess result = subprocess.run(["cat", "sample.txt"], stderr=subprocess.PIPE, text=True) print(result.stderr)
Sørg for at du ikke har en fil med navnet `sample.txt` i din arbeidsmappe. Verdien `PIPE` for nøkkelordargumentet `stderr` gjør at feilen returneres som et objekt. Dette objektet kan du senere få tilgang til via samme navn. Nøkkelordargumentet `text` sørger for at utdataene blir returnert som en streng.
Tilsvarende kan vi fange opp resultatet av kommandoen ved å bruke nøkkelordargumentet `stdout`.
import subprocess result = subprocess.run(["echo", "Hello, World!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) print(result.stdout)
subprocess.run() – input
Du kan gi input til kommandoer ved hjelp av nøkkelordargumentet `input`. Inputen må gis i strengformat. I tillegg må du sette nøkkelordargumentet `text` til `True`, siden standard er at inputen forventes i form av bytes.
La oss se på et eksempel:
import subprocess subprocess.run(["python3", "add.py"], text=True, input="2 3")
I eksemplet ovenfor forventer Python-skriptet `add.py` to tall som input. Vi har gitt denne inputen til Python-skriptet ved å bruke nøkkelordargumentet `input`.
subprocess.Popen()
Klassen `subprocess.Popen()` er mer avansert enn metoden `subprocess.run()`. Den tilbyr flere muligheter for å utføre kommandoer. For å bruke `Popen()` må vi først opprette en instans av klassen, og deretter kan vi bruke denne instansen til å utføre kommandoer, sjekke status, få utdata, gi input osv.
Det finnes flere metoder for klassen `subprocess.Popen()` som er nyttige å kjenne til. La oss se nærmere på disse med kodeeksempler.
wait()
Metoden `wait()` brukes til å vente til en kommando er fullført. Ingen kode etter `wait()` vil bli utført før kommandoen er ferdig. Her er et eksempel:
import subprocess process = subprocess.Popen(["ls", "-la"]) print("Completed!")
Når du kjører koden over vil du se at meldingen «Completed!» blir skrevet ut før kommandoen er ferdig. Dette kan vi unngå ved å bruke metoden `wait()`. Vi kan vente til kommandoen er ferdig før den neste linjen utføres.
import subprocess process = subprocess.Popen(["ls", "-la"]) process.wait() print("Completed!")
Når du kjører denne koden, vil du se at `wait()` fungerer som forventet. Utskriftssetningen utføres først etter at kommandoen er ferdig.
communicate()
Metoden `communicate()` brukes til å motta utdata, feilmeldinger og gi input til kommandoen. Den returnerer en tuppel som inneholder henholdsvis utdata og feil. La oss se på et eksempel:
import subprocess process = subprocess.Popen(["echo", "Hello, World!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) result = process.communicate() print(result)
subprocess.Popen() – input
Vi kan ikke sende input direkte til klassen `Popen()`. I stedet må vi bruke nøkkelordargumentet `stdin` for å gi input til kommandoen. Instansen av klassen `Popen` vil gi oss et `stdin`-objekt. Dette objektet har en metode som heter `write()` som vi kan bruke for å sende input til kommandoen.
Som tidligere nevnt, forventes input som standard i form av byte-lignende objekter. Derfor er det viktig å sette nøkkelordargumentet `text` til `True` når du oppretter instansen av `Popen`.
Her er et eksempel:
import subprocess process = subprocess.Popen(["python3", "add.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) process.stdin.write("2 3") process.stdin.close() print(process.stdout.read())
poll()
Metoden `poll()` brukes for å sjekke om utførelsen av en kommando er ferdig eller ikke. Metoden returnerer `None` dersom kommandoen fortsatt kjører. La oss illustrere dette med et eksempel:
import subprocess process = subprocess.Popen(['ping', '-c 5', 'geekflare.com'], stdout=subprocess.PIPE, text=True) while True: output = process.stdout.readline() if output: print(output.strip()) result = process.poll() if result is not None: break
I koden over bruker vi `ping`-kommandoen med 5 forespørsler. Vi har en evig løkke som fortsetter frem til utførelsen av kommandoen er ferdig. Vi bruker `poll()` for å sjekke status. Når `poll()` returnerer noe annet enn `None`, er kommandoen ferdig, og løkken avsluttes.
Utføre Bash-skript
Vi har nå sett på to måter å utføre kommandoer. La oss se på hvordan vi kan utføre bash-skript fra Python.
Modulen `subprocess` har en metode som heter `call`. Denne metoden brukes for å utføre bash-skript. Metoden returnerer utgangskoden fra bash-skriptet. Standard utgangskode for bash-skript er 0. Her er et eksempel:
Først, la oss opprette et bash-skript med navnet `practice.sh` med følgende innhold:
#!/bin/bash echo "Hello, World!" exit 1
Lag nå et Python-skript som utfører bash-skriptet:
import subprocess exit_code = subprocess.call('./practice.sh') print(exit_code)
Når du kjører Python-skriptet, vil du se følgende utdata:
Hello, World! 1
Konklusjon
Vi har nå sett hvordan man utfører både bash-kommandoer og bash-skript fra Python. Dette er et svært nyttig verktøy for automatisering.
Lykke til med kodingen! 👨💻