Jak uruchamiać skrypty bash za pomocą Pythona?

Jeśli używasz Linuksa, na pewno pokochasz polecenia powłoki.

A jeśli pracujesz z Pythonem, być może próbowałeś coś zautomatyzować. To sposób na zaoszczędzenie czasu. Możesz także mieć kilka skryptów bash do automatyzacji rzeczy.

Python jest przydatny do pisania skryptów niż bash. A zarządzanie skryptami Pythona jest łatwe w porównaniu do skryptów bash. Trudno będzie utrzymywać skrypty bash, gdy będą one rosły.

Ale co, jeśli masz już skrypty bash, które chcesz uruchomić za pomocą Pythona?

Czy istnieje sposób na wykonanie poleceń i skryptów bash w Pythonie?

Tak, Python ma wbudowany moduł o nazwie subprocess, który służy do wykonywania poleceń i skryptów w skryptach Pythona. Zobaczmy szczegółowo, jak wykonywać polecenia i skrypty bash w skryptach Pythona.

Wykonywanie poleceń Bash

Jak już zapewne zauważyłeś, podproces modułu służy do wykonywania poleceń i skryptów bash. Zapewnia różne metody i klasy dla tego samego.

Z modułu podprocesu należy wiedzieć głównie o jednej metodzie i jednej klasie. Są biegani i Popen. Te dwa pomagają nam wykonywać polecenia bash w skryptach Pythona. Zobaczmy je jeden po drugim.

podproces.uruchom()

Metoda subprocess.run() przyjmie listę ciągów jako argument pozycyjny. Jest to obowiązkowe, ponieważ zawiera polecenie bash i argumenty za nim. Pierwszą pozycją na liście jest nazwa polecenia, a pozostałe elementy to argumenty polecenia.

Zobaczmy szybki przykład.

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

Powyższy skrypt wyświetla listę wszystkich elementów w bieżącym katalogu roboczym, zgodnie z opisem skryptu. W powyższym skrypcie nie ma żadnych argumentów do polecenia. Wydaliśmy tylko polecenie bash. Możemy podać dodatkowe argumenty do polecenia ls, takie jak -l, -a, -la itp.

Zobaczmy szybki przykład z argumentami poleceń.

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

Powyższe polecenie wyświetla wszystkie pliki, w tym pliki ukryte wraz z uprawnieniami. Dostarczyliśmy argument la, który wyświetla dodatkowe informacje o plikach i katalogach oraz ukryte pliki.

Podczas pisania poleceń możemy popełnić błędy. Błędy będą wzrastać zgodnie z błędami. A co, jeśli chcesz je uchwycić i wykorzystać później? Tak, możemy to zrobić za pomocą argumentu słowa kluczowego stderr.

Zobaczmy przykład.

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

Upewnij się, że nie masz pliku o nazwie sample.txt w katalogu roboczym. Wartość argumentu stderr słowa kluczowego to PIPE, która pomaga zwrócić błąd w obiekcie. Możemy uzyskać do niego później dostęp pod tą samą nazwą. Argument tekstowy słowa kluczowego pomaga stwierdzić, że wynik powinien być łańcuchem.

Podobnie możemy przechwycić dane wyjściowe polecenia za pomocą argumentu słowa kluczowego stdout.

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

subprocess.run() – wejście

Możesz wprowadzić dane wejściowe do poleceń za pomocą argumentu wejściowego słowa kluczowego. Podamy dane wejściowe w formacie ciągu. Dlatego musimy ustawić tekst argumentu słowa kluczowego na True. Domyślnie zajmuje to w bajtach.

Spójrzmy na przykład.

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

W powyższym programie skrypt Pythona add.py przyjmie dwie liczby jako dane wejściowe. Daliśmy dane wejściowe do skryptu Pythona za pomocą argumentu słowa kluczowego input.

subproces.Popen()

Klasa subprocess.Popen() jest zaawansowana niż metoda subprocess.run(). Daje nam więcej możliwości wykonywania poleceń. Stworzymy instancję subprocess.Popen() i użyjemy jej do różnych rzeczy, takich jak poznanie stanu wykonania polecenia, uzyskanie danych wyjściowych, podanie danych wejściowych itp.,

Istnieje kilka metod klasy subprocess.Popen(), które musimy znać. Zobaczmy je jeden po drugim wraz z przykładami kodu.

czekać

Służy do oczekiwania na zakończenie wykonania polecenia. Kolejne wiersze skryptu Pythona nie zostaną wykonane do czasu zakończenia poprzedniego polecenia napisanego po metodzie wait. Zobaczmy przykład.

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

Uruchom powyższy kod i obserwuj dane wyjściowe. Zobaczysz, że komunikat Ukończono! jest wypisywany przed wykonaniem polecenia. Możemy tego uniknąć, stosując metodę oczekiwania. Poczekajmy do zakończenia polecenia.

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

print("Completed!")

Jeśli zobaczysz dane wyjściowe dla powyższego kodu, zdasz sobie sprawę, że czekanie faktycznie działa. Instrukcja print jest wykonywana po zakończeniu wykonywania polecenia.

komunikować się

Metoda komunikowania się jest używana do uzyskania danych wyjściowych, błędów i wprowadzenia danych do polecenia. Zwraca krotkę zawierającą odpowiednio dane wyjściowe i błąd. Zobaczmy przykład.

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

subprocess.Popen() – wejście

Nie możemy przekazać danych wejściowych bezpośrednio do klasy Popen. Musimy użyć argumentu kluczowego o nazwie stdin, aby podać dane wejściowe do polecenia. Instancja klasy Popen dostarczy nam obiektu stdin. Ma metodę o nazwie write, która służy do wprowadzania danych wejściowych do polecenia.

Jak wspomnieliśmy wcześniej, domyślnie przyjmuje dane wejściowe jako obiekty podobne do bajtów. Nie zapomnij więc ustawić tekstu argumentu słowa kluczowego na True podczas tworzenia instancji Popen.

Zobaczmy przykład.

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

głosowanie

Poll metoda służy do sprawdzenia, czy wykonanie polecenia zostało zakończone, czy nie. Ta metoda zwróci None, jeśli polecenie nadal jest wykonywane. Zobaczmy przykład.

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

W powyższym kodzie użyliśmy polecenia ping z 5 żądaniami. Istnieje nieskończona pętla, która iteruje aż do zakończenia wykonywania polecenia. Wykorzystaliśmy metodę poll do sprawdzenia statusu wykonania polecenia. Jeśli sonda metody zwróci kod inny niż None, wykonanie zostanie zakończone. I nieskończona pętla pęka.

Wykonywanie skryptów Bash

Widzieliśmy dwa sposoby wykonywania poleceń. Zobaczmy teraz, jak wykonać skrypty bash w skryptach Pythona.

Podproces posiada metodę o nazwie call. Ta metoda służy do wykonywania skryptów bash. Metoda zwraca kod wyjścia ze skryptu bash. Domyślny kod wyjścia dla skryptów bash to 0. Zobaczmy przykład.

Utwórz skrypt bash o nazwie praktyka.sh w następujący sposób.

#!/bin/bash

echo "Hello, World!"
exit 1

Teraz napisz skrypt Pythona i wykonaj powyższy skrypt bash.

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

Otrzymasz następujące dane wyjściowe po uruchomieniu powyższego skryptu Pythona.

Hello, World!
1

Wniosek

Widzieliśmy, jak wykonywać polecenia i skrypty basha w Pythonie. Możesz ich użyć do wydajniejszej automatyzacji.

Szczęśliwego kodowania 👨‍💻