Skip to content
Python Basics: Running Commands with subprocess

Python Basics: Running Commands with subprocess

October 11, 2026

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.py

Output:

hello; world
exit=0

sys.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.py

Output:

exit=2
missing input

An 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.py

Output:

Command timed out

run() 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.

Last updated on