Hur kör man bash-skript med Python?

Om du använder Linux skulle du definitivt älska skalkommandona.

Och om du arbetar med Python kan du ha försökt att automatisera saker. Det är ett sätt att spara tid. Du kan också ha några bash-skript för att automatisera saker.

Python är praktiskt att skriva skript än bash. Och att hantera Python-skript är enkelt jämfört med bash-skript. Du kommer att finna det svårt att underhålla bash-skripten när de väl växer.

Men vad händer om du redan har bash-skript som du vill köra med Python?

Finns det något sätt att köra bash-kommandon och skript i Python?

Ja, Python har en inbyggd modul som heter subprocess som används för att köra kommandon och skript i Python-skript. Låt oss se hur man utför bash-kommandon och skript i Python-skript i detalj.

Utför bash-kommandon

Som du kanske redan har sett används modulens underprocess för att utföra bash-kommandon och skript. Det ger olika metoder och klasser för detsamma.

Det finns huvudsakligen en metod och en klass att känna till från delprocessmodulen. De är körda och Popen. Dessa två hjälper oss att köra bash-kommandona i Python-skript. Låt oss se dem en efter en.

subprocess.run()

Metoden subprocess.run() tar en lista med strängar som ett positionsargument. Detta är obligatoriskt eftersom det har bash-kommandot och argument för det. Det första objektet i listan är kommandots namn och de återstående objekten är argumenten till kommandot.

Låt oss se ett snabbt exempel.

import subprocess
subprocess.run(["ls"])

Skriptet ovan listar alla objekt i den aktuella arbetskatalogen som skriptet ligger. Det finns inga argument för kommandot i skriptet ovan. Vi har bara gett bash-kommandot. Vi kan ge ytterligare argument till ls-kommandot som -l, -a, -la, etc.

Låt oss se ett snabbt exempel med kommandoargument.

import subprocess
subprocess.run(["ls", "-la"])

Ovanstående kommando visar alla filer inklusive dolda filer tillsammans med behörigheterna. Vi har tillhandahållit argumentet la som visar filer och kataloger extra information och dolda filer.

Det kan sluta med att vi gör några misstag när vi skriver kommandona. Fel kommer att öka enligt misstagen. Vad händer om du vill fånga dem och använda dem senare? Ja, vi kan göra det med hjälp av sökordsargumentet stderr.

Låt oss se ett exempel.

import subprocess
result = subprocess.run(["cat", "sample.txt"], stderr=subprocess.PIPE, text=True)
print(result.stderr)

Se till att du inte har filen med namnet sample.txt i arbetskatalogen. Värdet på nyckelordsargumentet stderr är PIPE som hjälper till att returnera felet i ett objekt. Vi kan komma åt det senare med samma namn. Och sökordsargumenttexten hjälper till att tala om att utdata ska vara en sträng.

På samma sätt kan vi fånga resultatet av kommandot med hjälp av stdout nyckelordsargumentet.

import subprocess
result = subprocess.run(["echo", "Hello, World!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
print(result.stdout)

subprocess.run() – input

Du kan ge input till kommandona med hjälp av input nyckelordsargumentet. Vi kommer att ge input i ett strängformat. Så vi måste ställa in nyckelordsargumenttexten till True. Som standard tar den det i byte.

Låt oss titta på ett exempel.

import subprocess
subprocess.run(["python3", "add.py"], text=True, input="2 3")

I programmet ovan kommer Python-skriptet add.py att ta två siffror som indata. Vi har gett input till Python-skriptet med hjälp av input nyckelordet argument.

subprocess.Popen()

Klassen subprocess.Popen() är avancerad än metoden subprocess.run(). Det ger oss fler alternativ för att utföra kommandona. Vi kommer att skapa en instans av subprocess.Popen() och använda den för olika saker som att veta statusen för kommandoexekveringen, få utdata, ge input, etc..,

Det finns flera metoder för klassen subprocess.Popen() som vi behöver känna till. Låt oss se dem en efter en tillsammans med kodexemplen.

vänta

Den används för att vänta tills genomförandet av kommandot är klart. Nästa rader i Python-skriptet kommer inte att köras förrän det föregående kommandot som skrivs efter väntemetoden har slutförts. Låt oss se exemplet.

import subprocess
process = subprocess.Popen(["ls", "-la"])
print("Completed!")

Kör ovanstående kod och observera resultatet. Du kommer att se att meddelandet Slutfört! skrivs ut innan kommandot utförs. Vi kan undvika det med väntemetoden. Låt oss vänta tills kommandot är klart.

import subprocess
process = subprocess.Popen(["ls", "-la"])
process.wait()

print("Completed!")

Om du ser utdata för ovanstående kod kommer du att inse att väntan faktiskt fungerar. Utskriftssatsen exekveras efter att kommandot har utförts.

kommunicera

Metoden communicate används för att få utdata, fel och ge input till kommandot. Den returnerar en tuppel som innehåller utdata respektive fel. Låt oss se ett exempel.

import subprocess
process = subprocess.Popen(["echo", "Hello, World!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
result = process.communicate()
print(result)

subprocess.Popen() – ingång

Vi kan inte skicka in input till klassen Popen direkt. Vi måste använda nyckelordsargumentet stdin för att ge indata till kommandot. Förekomsten av klassen Popen kommer att ge oss stdin-objekt. Den har en metod som heter write som används för att ge indata till kommandot.

Som vi diskuterade tidigare kommer det att ta indata som byteliknande objekt som standard. Så glöm inte att ställa in nyckelordsargumenttexten till True när du skapar instansen av Popen.

Låt oss se ett exempel.

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

opinionsundersökning

Metodundersökningen används för att kontrollera om exekveringen av kommandot är slutfört eller inte. Denna metod returnerar Ingen om kommandot fortfarande körs. Låt oss se ett exempel.

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 ovanstående kod har vi använt kommandot ping med 5 förfrågningar. Det finns en oändlig loop som itererar tills kommandokörningen är klar. Vi har använt metoden poll för att kontrollera statusen för kommandoexekveringen. Om metoden poll returnerar annan kod än Ingen, slutförs exekveringen. Och den oändliga slingan bryts.

Utför Bash-skript

Vi har sett två sätt att utföra kommandona. Låt oss nu se hur man kör bash-skripten i Python-skript.

Delprocessen har en metod som kallas call. Denna metod används för att köra bash-skripten. Metoden returnerar utgångskoden från bash-skriptet. Standardexitkoden för bash-skripten är 0. Låt oss se ett exempel.

Skapa ett bash-skript med namnet practice.sh enligt följande.

#!/bin/bash

echo "Hello, World!"
exit 1

Skriv nu ett Python-skript och kör ovanstående bash-skript.

import subprocess
exit_code = subprocess.call('./practice.sh')
print(exit_code)

Du kommer att få följande utdata när du kör ovanstående Python-skript.

Hello, World!
1

Slutsats

Vi har sett hur man kör bash-kommandon och skript i Python. Du kan använda dem för att automatisera saker mer effektivt.

Glad kodning 👨‍💻