subprocess can be used to run a command on the same system as your Python program. Here is the minimal boilerplate code without any error handling to create the /tmp/foo directory on the same system as your Python program.
#!/usr/bin/python3
import subprocess
subprocess.Popen("mkdir /tmp/foo", shell=True)
Here is a more practical example, with try/except/else error handling.
#!/usr/bin/python3
import subprocess
try:
subprocess.Popen("mkdir /tmp/foo", shell=True)
except Exception as exception:
print(exception)
else:
print(f"successfully created the /tmp/foo directory")
Almost always, you are going to want to capture both stdout and stderr.
#!/usr/bin/python3
import subprocess
command = "pwd"
try:
stdout, stderr = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
except Exception as exception:
print(f"got the following exception: {exception}")
else:
stdout = stdout.decode('utf-8').strip()
stderr = stderr.decode('utf-8').strip()
if stdout:
print(f"stdout = {stdout}")
if stderr:
print(f"stderr = {stderr}")
streamdata can be used if you want to get the return code of the command.
stdout = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
streamdata = stdout.communicate()[0]
rc = stdout.returncode
print(f"rc = {rc}")
Notice the above example uses Popen. https://docs.python.org/3/library/subprocess.html#using-the-subprocess-module says:
The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly.
For this reason, I'd always go with run instead of Popen, if you can.
#!/usr/bin/python3
import subprocess
command = "ls /tmp"
command_args = command.split()
response = subprocess.run(command_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(f"stdout = {response.stdout.decode('utf-8').strip()}")
print(f"stderr = {response.stderr.decode('utf-8').strip()}")
print(f"returncode = {response.returncode}")
If you command includes a pipe and grep, then you'll probably need to go with shell=True.
#!/usr/bin/python3
import subprocess
command = "ls /tmp | grep foo"
response = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(f"stdout = {response.stdout.decode('utf-8').strip()}")
print(f"stderr = {response.stderr.decode('utf-8').strip()}")
print(f"returncode = {response.returncode}")
You can reduce the markup in subprocess.run by using from subprocess import PIPE and then you can use stdout=PIPE instead of stdout=subprocess.PIPE.
#!/usr/bin/python3
import subprocess
from subprocess import PIPE
command = "ls /tmp | grep foo"
response = subprocess.run(command, shell=True, stdout=PIPE, stderr=PIPE)
print(f"stdout = {response.stdout.decode('utf-8').strip()}")
print(f"stderr = {response.stderr.decode('utf-8').strip()}")
print(f"returncode = {response.returncode}")
Did you find this article helpful?
If so, consider buying me a coffee over at