How can I launch a bash command with multiple args (for example "
sudo apt update") from a python script?
@milne's answer works, but
subprocess.call() gives you little feedback.
I prefer to use
subprocess.check_output() so you can analyse what was printed to stdout:
import subprocess res = subprocess.check_output(["sudo", "apt", "update"]) for line in res.splitlines(): # process the output line by line
check_output throws an error on on-zero exit of the invoked command
Please note that this doesn't invoke
bash or another shell if you don't specify the
shell keyword argument to the function (the same is true for
subprocess.call(), and you shouldn't if not necessary as it imposes a security hazard), it directly invokes the command.
If you find yourself doing a lot of (different) command invocations from Python, you might want to look at plumbum. With that you can do the (IMO) more readable:
from plumbum.cmd import sudo, apt, echo, cut res = sudo[apt["update"]]() chain = echo["hello"] | cut["-c", "2-"] chain()
The subprocess module is designed to do this:
import subprocess subprocess.call(["sudo", "apt", "update"])
If you would like the script to terminate if the command fails, you might consider using
check_call() instead of parsing the return code yourself:
subprocess.check_call(["sudo", "apt", "update"])
Also you can use 'os.popen'.
import os command = os.popen('ls -al') print(command.read()) print(command.close())
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
For python 3.5 and more you can use:
import subprocess try: result = subprocess.run("sudo apt update", check=True, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except subprocess.CalledProcessError as err: raise Exception(str(err.stderr.decode("utf-8"))) except Exception as err: raise Exception(err) else: return result.stdout.decode("utf-8")