Python Basics: Running Commands with subprocess
Python’s standard-library subprocess module runs another program and collects its result. These Linux examples use Python 3.12 or newer and only launch small Python commands.
Pass arguments as a list
Save as demo_subprocess_1.py:
import subprocess
import sys
result = subprocess.run(
[sys.executable, "-c", "import sys; print(sys.argv[1])", "hello; world"],
capture_output=True,
text=True,
check=True,
)
print(result.stdout, end="")
print(f"exit={result.returncode}")Run:
python3 demo_subprocess_1.pyOutput:
hello; world
exit=0sys.executable selects the current Python interpreter. Each list item is one argument, including spaces. The default shell=False leaves the semicolon as ordinary text.
capture_output=True collects stdout and stderr separately. text=True returns strings instead of bytes. Without capture, output normally goes to the parent’s streams.
Catch a failed command
check=True raises CalledProcessError for a nonzero exit status. The default, check=False, returns the status without raising.
Save as demo_subprocess_2.py:
import subprocess
import sys
try:
subprocess.run(
[sys.executable, "-c",
"import sys; print('missing input', file=sys.stderr); sys.exit(2)"],
capture_output=True,
text=True,
check=True,
)
except subprocess.CalledProcessError as error:
print(f"exit={error.returncode}")
print(error.stderr, end="")Run:
python3 demo_subprocess_2.pyOutput:
exit=2
missing inputAn executable that cannot be found raises FileNotFoundError instead.
Limit how long a command runs
Save as demo_subprocess_3.py:
import subprocess
import sys
try:
subprocess.run(
[sys.executable, "-c", "import time; time.sleep(60)"],
timeout=0.1,
check=True,
)
except subprocess.TimeoutExpired:
print("Command timed out")Run:
python3 demo_subprocess_3.pyOutput:
Command timed outrun() kills and waits for the direct child when this timeout expires. Process creation can delay the timeout; it is not an exact wall-clock deadline.
Keep shell=False and pass data as arguments. This avoids shell parsing, but the target program can still interpret arguments as options or code. Never substitute untrusted text for the Python code passed to -c here.
Reference
Python subprocess documentation
Acknowledgements
This post was created with assistance from AI.