Subprocess
Python · Reference cheat sheet
Subprocess
Python · Reference cheat sheet
📋 Overview
subprocess runs external programs. Prefer subprocess.run(...) over older Popen/call helpers for most scripts. Capture output when you need it; raise on failure with check=True.
🔧 Core concepts
| API | Role |
|---|---|
subprocess.run(args, ...) | Run and wait; returns CompletedProcess |
capture_output=True | Capture stdout/stderr as bytes |
text=True / encoding= | Decode streams as str |
check=True | Raise CalledProcessError on non-zero |
cwd= / env= | Working dir / environment |
timeout= | Kill if too slow |
shell=True | Run via shell (usually avoid) |
CompletedProcess.returncode | Exit status |
Pass args as a list unless you truly need shell features.
💡 Examples
Basic run:
import subprocess
r = subprocess.run(["python", "-c", "print(1+1)"], capture_output=True, text=True)
print(r.returncode, r.stdout.strip())check + capture:
import subprocess
try:
r = subprocess.run(
["git", "rev-parse", "HEAD"],
capture_output=True,
text=True,
check=True,
)
print(r.stdout.strip())
except subprocess.CalledProcessError as e:
print("failed:", e.returncode, e.stderr)cwd and env:
import os
import subprocess
env = {**os.environ, "MY_FLAG": "1"}
subprocess.run(["ls"], cwd="/tmp", env=env, check=True)Avoid shell when possible:
import subprocess
# Good: list form, no shell
subprocess.run(["echo", "hello"], check=True)
# Risky: shell=True with untrusted input → injection
# subprocess.run(f"echo {user}", shell=True) # DON'T⚠️ Pitfalls
shell=True+ unsanitized input enables command injection — use argument lists.- Without
capture_output/stdout=PIPE, output goes to the console. - Forgotten
text=Trueleavesbytesin.stdout. check=False(default) hides failures — setcheck=Trueor inspectreturncode.- Deadlocks are rare with
run; with rawPopenpipes, always drain or usecommunicate.