jak wykonać polecenie bash w skrypcie python

Odpowiedzi:

17

Odpowiedź @ milne działa, ale subprocess.call()daje niewiele informacji zwrotnych.

Wolę używać subprocess.check_output(), abyś mógł przeanalizować, co zostało wydrukowane na standardowe wyjście:

 import subprocess
 res = subprocess.check_output(["sudo", "apt", "update"])
 for line in res.splitlines():
     # process the output line by line

check_output zgłasza błąd przy zerowym wyjściu z wywołanej komendy

Pamiętaj, że to nie wywołuje bashani innej powłoki, jeśli nie podasz shellargumentu słowa kluczowego dla funkcji (to samo dotyczy subprocess.call(), i nie powinieneś, jeśli nie jest to konieczne, ponieważ stanowi zagrożenie bezpieczeństwa), bezpośrednio wywołuje Komenda.

Jeśli zauważysz, że wykonujesz wiele (różnych) wywołań poleceń z Pythona, możesz przyjrzeć się pionowi . Dzięki temu możesz zrobić (IMO) bardziej czytelny:

from plumbum.cmd import sudo, apt, echo, cut

res = sudo[apt["update"]]()
chain = echo["hello"] | cut["-c", "2-"]
chain()
Anthon
źródło
Czy zaleca się użycie ( os.popenlub os.system), np .: res = os.popen('sudo apt update').read()? @Anthon
alper
1
@alper Przeczytaj 0324 python.org/dev/peps/pep-0324 . To wyjaśnia uzasadnienie dla podejmowania subprocesschoć os.systemi os.popenjuż istniał. Takie PEP nie są łatwe do zaakceptowania. Kilka osób zastanowiło się nad tym znacznie więcej niż ty lub ja. I subprocesspoprawił się od 2003 roku, pozostałe wciąż są dostępne dla kompatybilności wstecznej. Czy os.systemzredagowałeś stronę podręcznika: Moduł podprocesu zapewnia potężniejsze możliwości tworzenia nowych procesów i wyszukiwania ich wyników; korzystanie z tego modułu jest lepsze niż korzystanie z tej funkcji.
Anthon
1
@alper Tak, możesz. Jak już wskazałem, jest to potencjalne zagrożenie bezpieczeństwa, więc nie wiem, dlaczego uważasz, że jest to zalecane. A inwokowanie sudotylko pogorszy to. Może lepszym rozwiązaniem jest użycie python-apt (sam tego nie analizowałem).
Anthon
1
@alper w takim przypadku poważnie przyjrzyj się pionowi , warto z tym przyspieszyć.
Anthon
1
@alper Jeśli korzystasz z Python3, musisz to zrobić, w Python2 nie. Nie używaj komentarzy tutaj jako systemu czatu. Jeśli masz pytanie, opublikuj je jako takie.
Anthon
8

Możliwe jest użycie bash jako programu, z parametrem -c do wykonania poleceń:

Przykład:

bashCommand = "sudo apt update"
output = subprocess.check_output(['bash','-c', bashCommand])
Brzytwa
źródło
7

Podproces moduł został zaprojektowany, aby to zrobić:

import subprocess
subprocess.call(["sudo", "apt", "update"])

Jeśli chcesz, aby skrypt zakończył się w przypadku niepowodzenia polecenia, możesz rozważyć użycie check_call()zamiast samodzielnego analizowania kodu powrotu:

subprocess.check_call(["sudo", "apt", "update"])
Milind Dumbare
źródło
dało mi to następujący ślad: Traceback (most recent call last): File "/home/Dremor/test.py", line 3, in <module> subprocess.call('sudo', 'yum', 'update') File "/usr/lib64/python3.4/subprocess.py", line 537, in call with Popen(*popenargs, **kwargs) as p: File "/usr/lib64/python3.4/subprocess.py", line 767, in __init__ raise TypeError("bufsize must be an integer") TypeError: bufsize must be an integer (używam yum, ponieważ używam Fedory jako głównego systemu operacyjnego)
Dremor,
3
Zapomniałeś nawiasów kwadratowych
Milind Dumbare
1
Zauważ też, że subprocess.call()blokuje się, a subprocess.Popen()nie blokuje.
heemayl
Co rozumiesz przez „blokowanie”? @heemayl
alper
2

Możesz także użyć „os.popen”.

Przykład:

import os

command = os.popen('ls -al')
print(command.read())
print(command.close())

Wynik:

total 16
drwxr-xr-x 2 root root 4096 ago 13 21:53 .
drwxr-xr-x 4 root root 4096 ago 13 01:50 ..
-rw-r--r-- 1 root root 1278 ago 13 21:12 bot.py
-rw-r--r-- 1 root root   77 ago 13 21:53 test.py

None
ricardo130
źródło
0

użyj modułu podprocesu

import subprocess
command = 'sudo apt update'
subprocess.check_call(command.split())
Fred
źródło
dlaczego dostaję błąd, gdy go używam
aquagremlin
subprocess.check_call ([„sudo”, „apt”, „update”])
aquagremlin
CalledProcessError Traceback (ostatnie ostatnie połączenie) <ipython-input-21-33ce645708e7> w <module> () ----> 1 subprocess.check_call (["sudo", "apt", "update"]) / usr / lib / python2.7 / subprocess.pyc w call_call (* popenargs, ** kwargs) 188, jeśli cmd to None: 189 cmd = popenargs [0] -> 190 raise CalledProcessError (retcode, cmd) 191 return 0 192 CalledProcessError: Command „[„ sudo ”,„ apt ”,„ update ”]” zwróciło niezerowy status wyjścia 1
aquagremlin
ten błąd występuje tylko wtedy, gdy uruchomię go w notatniku
jupyter
może zacznę nowe pytanie, ponieważ jest to ot
aquagremlin