Subprocess Call in Python#
subprocess.run()
#
subprocess.run()
is high-level and easy to use. It is the recommended way to run a command in Python.
For example, we want to grab the output of the command ls -l
.
import subprocess
completed_proc = subprocess.run(
["ls", "-l"],
capture_output=True,
text=True,
)
print(completed_proc.stdout)
Warning
subprocess.run()
is only available >= Python 3.5.capture_output=True
andtext=True
are only available >= Python 3.7.
If you use Python 3.6, you may use equivalent code:
completed_proc = subprocess.run(
["ls", "-l"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
)
print(completed_proc.stdout)
capture_output=True
is simply a shortcut tostdout=subprocess.PIPE
+stderr=subprocess.PIPE
.text=True
is an alias touniversal_newlines=True
.
subprocess.run()
accepts the shell command as a list of arguments. But instead of spiting the command into a list manually, we can use the shlex.split()
function instead.
import shlex
import subprocess
completed_proc = subprocess.run(
shlex.split("ls -l"),
capture_output=True,
text=True,
)
print(completed_proc.stdout)
Another way is to use the shell=True
keyword argument. When shell=True
is specified, the command will be executed in the system shell program, which is equivalent to executing the command in a shell terminal.
import subprocess
completed_proc = subprocess.run(
"ls -l",
shell=True,
capture_output=True,
text=True,
)
print(completed_proc.stdout)
Note
By specifying shell=True
, you can also make use of shell features like:
- filename wildcards:
rm tmp_*.txt
- environment variable expansion:
echo $USER
- home directory expansion:
cd ~
- pipes:
nvidia-smi | grep clock
Like this will run as expected:
subprocess.run("ls ~", shell=True)
But this will cause an error:
>>> subprocess.run(["ls", "~"])
ls: ~: No such file or directory
- This is because the program
ls
does not recognize~
as a valid path, only the shell program does.
subprocess.run()
is a blocking function. It will wait until the command finishes before returning. If you wish to execute a command in the background, you should use the subprocess.Popen()
function instead.