Ukoliko koristite Linux, komande ljuske će vam se zasigurno dopasti.
Ako radite s Python-om, verovatno ste pokušavali da automatizujete neke zadatke. To je odličan način da uštedite vreme. Možda već imate i neke bash skripte za automatizaciju.
Python je pogodniji za pisanje skripti od bash-a. Upravljanje Python skriptama je jednostavnije u poređenju sa bash skriptama. Kada vam se projekti budu širili, biće vam teže održavati bash skripte.
Ali šta ako već posedujete bash skripte koje želite da pokrenete unutar Python okruženja?
Postoji li način da se izvrše bash komande i skripte iz Python-a?
Da, Python sadrži ugrađeni modul pod imenom ‘subprocess’ koji služi za izvršavanje komandi i skripti direktno iz Python skripti. Pogledajmo detaljnije kako izvesti bash komande i skripte unutar Python skripti.
Izvršavanje Bash Komandi
Kao što ste možda već i pretpostavili, modul ‘subprocess’ se koristi za izvršavanje bash komandi i skripti. On nudi razne metode i klase za to.
Postoji primarno jedna metoda i jedna klasa iz modula ‘subprocess’ koje su ključne za razumevanje. To su ‘run’ i ‘Popen’. Te dve opcije nam pomažu pri izvršavanju bash komandi u Python skriptama. Hajde da ih pogledamo jednu po jednu.
subprocess.run()
Metoda ‘subprocess.run()’ prihvata listu stringova kao pozicioni argument. Ovo je neophodno jer sadrži bash komandu i argumente za nju. Prvi element liste je ime komande, a svi ostali elementi su argumenti komande.
Pogledajmo jedan brz primer:
import subprocess subprocess.run(["ls"])
Gornja skripta prikazuje sve stavke u trenutnom radnom direktorijumu. U ovom primeru, komanda nema argumente. Dali smo samo bash komandu. Možemo dodati dodatne argumente komandi ‘ls’ kao što su -l, -a, -la, itd.
Pogledajmo brz primer sa argumentima komande:
import subprocess subprocess.run(["ls", "-la"])
Ova komanda prikazuje sve fajlove, uključujući skrivene, zajedno sa njihovim dozvolama. Naveli smo argument ‘la’ koji prikazuje fajlove i direktorijume, dodatne informacije i skrivene fajlove.
Moguće je da ćete naići na greške prilikom pisanja komandi. Te greške se mogu povećavati kako program raste. Šta ako želite da ih uhvatite i analizirate kasnije? Da, to je moguće pomoću argumenta ‘stderr’.
Pogledajmo primer:
import subprocess result = subprocess.run(["cat", "sample.txt"], stderr=subprocess.PIPE, text=True) print(result.stderr)
Uverite se da nemate fajl pod imenom ‘sample.txt’ u vašem radnom direktorijumu. Vrednost argumenta ‘stderr’ je ‘PIPE’ što nam omogućava da vratimo grešku u objekat. Možemo pristupiti grešci kasnije koristeći isto ime. ‘text’ argument signalizira da izlaz treba da bude string.
Slično, možemo dobiti izlaz komande koristeći argument ‘stdout’.
import subprocess result = subprocess.run(["echo", "Hello, World!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) print(result.stdout)
subprocess.run() – Ulaz
Možete uneti podatke za komande koristeći argument ‘input’. Unos ćemo dati u formatu stringa. Zbog toga, neophodno je da podesimo ‘text’ argument na ‘True’. Podrazumevano, ulaz se uzima u bajtovima.
Pogledajmo primer:
import subprocess subprocess.run(["python3", "add.py"], text=True, input="2 3")
U gornjem programu, Python skripta ‘add.py’ će primiti dva broja kao ulaz. Mi smo prosledili ulaz za Python skriptu koristeći argument ‘input’.
subprocess.Popen()
Klasa ‘subprocess.Popen()’ je naprednija od metode ‘subprocess.run()’. Ona nam daje više opcija za izvršavanje komandi. Kreiraćemo instancu ‘subprocess.Popen()’ i koristiti je za različite stvari kao što su praćenje statusa izvršenja komande, dobijanje izlaza, davanje ulaza itd.
Postoji nekoliko metoda klase ‘subprocess.Popen()’ koje je korisno znati. Hajde da ih pogledamo jednu po jednu, zajedno sa primerima koda.
wait
Metoda ‘wait’ se koristi za pauziranje izvršavanja programa sve dok se data komanda ne završi. Sledeći redovi Python skripte neće se izvršiti sve dok se pređašnja komanda ne izvrši. Pogledajmo primer:
import subprocess process = subprocess.Popen(["ls", "-la"]) print("Completed!")
Pokrenite gornji kod i obratite pažnju na izlaz. Videćete da se poruka „Completed!“ štampa pre izlaza komande. To možemo izbeći pomoću ‘wait’ metode. Sačekajmo da se komanda završi:
import subprocess process = subprocess.Popen(["ls", "-la"]) process.wait() print("Completed!")
Ako pogledate izlaz za gornji kod, videćete da ‘wait’ metoda zaista radi. Komanda za štampanje se izvršava tek nakon završetka izvršenja komande.
communicate
Metoda ‘communicate’ se koristi za dobijanje izlaza, grešaka i davanje ulaza komandi. Ona vraća torku koja sadrži izlaz i grešku redom. Pogledajmo primer:
import subprocess process = subprocess.Popen(["echo", "Hello, World!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) result = process.communicate() print(result)
subprocess.Popen() – Ulaz
Ne možemo direktno proslediti ulaz klasi ‘Popen’. Moramo koristiti argument ‘stdin’ da bismo prosledili ulaz komandi. Instanca klase ‘Popen’ će nam pružiti ‘stdin’ objekat. Ovaj objekat ima metodu ‘write’ koja služi za davanje ulaza komandi.
Kao što je ranije pomenuto, po podrazumevanom podešavanju ulaz se uzima kao bajt-sličan objekat. Zato ne zaboravite da podesite ‘text’ argument na ‘True’ kada pravite instancu klase ‘Popen’.
Pogledajmo primer:
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
Metoda ‘poll’ se koristi za proveru da li je izvršenje komande završeno ili ne. Ova metoda će vratiti ‘None’ ukoliko se komanda još uvek izvršava. Pogledajmo primer:
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
U gornjem kodu, koristili smo komandu ‘ping’ sa 5 zahteva. Postoji beskonačna petlja koja se ponavlja sve dok se ne završi izvršenje komande. Koristili smo ‘poll’ metodu da proverimo status izvršenja komande. Ukoliko ‘poll’ metoda vrati kod koji nije ‘None’, izvršenje se završava i beskonačna petlja se prekida.
Izvršavanje Bash Skripti
Videli smo dva načina za izvršavanje komandi. Sada, pogledajmo kako se izvršavaju bash skripte u Python skriptama.
Modul ‘subprocess’ poseduje metodu ‘call’. Ova metoda se koristi za izvršavanje bash skripti. Metoda vraća izlazni kod iz bash skripte. Po podrazumevanom podešavanju izlazni kod za bash skripte je 0. Pogledajmo primer:
Kreirajte bash skriptu pod imenom ‘practice.sh’ na sledeći način:
#!/bin/bash echo "Hello, World!" exit 1
Sada, napišite Python skriptu i izvršite gornju bash skriptu:
import subprocess exit_code = subprocess.call('./practice.sh') print(exit_code)
Kada pokrenete gornju Python skriptu, dobićete sledeći izlaz:
Hello, World! 1
Zaključak
Videli smo kako se izvršavaju bash komande i skripte u Python-u. Ove tehnike možete koristiti da biste efikasnije automatizovali vaše zadatke.
Srećno kodiranje 👨💻