Python Session 05: Subprocess
Shell integration. This session covers running external commands, capturing output, and environment handling.
Pre-Session State
-
Understand functions and classes
-
Can work with files
-
Know string processing
Lesson 1: Basic subprocess.run
Concept: Use subprocess.run() to execute commands.
Exercise 1.1: Simple command
import subprocess
result = subprocess.run(['ls', '-la', '/tmp'], capture_output=True, text=True)
print(result.stdout)
print(f"Return code: {result.returncode}")
Exercise 1.2: Check return code
import subprocess
result = subprocess.run(['ping', '-c', '1', 'localhost'], capture_output=True, text=True)
if result.returncode == 0:
print("Host is reachable")
else:
print("Host unreachable")
print(result.stderr)
Exercise 1.3: Raise on error
import subprocess
try:
result = subprocess.run(['ls', '/nonexistent'], capture_output=True, text=True, check=True)
except subprocess.CalledProcessError as e:
print(f"Command failed: {e}")
print(f"stderr: {e.stderr}")
Lesson 2: Shell Commands
Concept: Use shell=True for shell features (pipes, etc).
Exercise 2.1: Shell pipeline
import subprocess
# Note: shell=True has security implications - don't use with untrusted input
result = subprocess.run('ps aux | grep python | head -5', shell=True, capture_output=True, text=True)
print(result.stdout)
Exercise 2.2: Better: avoid shell=True
import subprocess
# Safer: pipe between processes
ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
grep = subprocess.Popen(['grep', 'python'], stdin=ps.stdout, stdout=subprocess.PIPE)
ps.stdout.close()
output = grep.communicate()[0]
print(output.decode())
Lesson 3: Environment Variables
Concept: Access and modify environment for subprocesses.
Exercise 3.1: Read environment
import os
print(os.environ.get('HOME'))
print(os.environ.get('VAULT_ADDR', 'not set'))
# All environment
for key, value in os.environ.items():
if 'PATH' in key:
print(f"{key}: {value[:50]}...")
Exercise 3.2: Set environment for subprocess
import subprocess
import os
my_env = os.environ.copy()
my_env['MY_VAR'] = 'my_value'
result = subprocess.run(['printenv', 'MY_VAR'], capture_output=True, text=True, env=my_env)
print(result.stdout) # my_value
Exercise 3.3: Expand variables
import os
path = os.path.expandvars('$HOME/.ssh/config')
print(path) # /home/user/.ssh/config
user_home = os.path.expanduser('~')
print(user_home) # /home/user
Lesson 4: Practical Patterns
Concept: Real-world subprocess patterns.
Exercise 4.1: Run and parse JSON output
import subprocess
import json
result = subprocess.run(['kubectl', 'get', 'pods', '-o', 'json'], capture_output=True, text=True)
if result.returncode == 0:
data = json.loads(result.stdout)
for pod in data.get('items', []):
print(pod['metadata']['name'])
Exercise 4.2: Timeout handling
import subprocess
try:
result = subprocess.run(['sleep', '10'], timeout=2, capture_output=True)
except subprocess.TimeoutExpired:
print("Command timed out")
Exercise 4.3: Working directory
import subprocess
result = subprocess.run(['pwd'], capture_output=True, text=True, cwd='/tmp')
print(result.stdout.strip()) # /tmp
result = subprocess.run(['git', 'status'], capture_output=True, text=True,
cwd='/home/user/project')
Exercise 4.4: Build command dynamically
import subprocess
import shlex
host = "10.50.1.110"
cmd = ['ssh', '-o', 'ConnectTimeout=5', host, 'uptime']
result = subprocess.run(cmd, capture_output=True, text=True)
print(result.stdout)
# If you have a string command, use shlex.split
cmd_str = "ls -la /tmp"
cmd_list = shlex.split(cmd_str)
print(cmd_list) # ['ls', '-la', '/tmp']
Summary: What You Learned
| Concept | Syntax | Example |
|---|---|---|
Run command |
|
|
Capture output |
|
|
Text mode |
|
Returns str instead of bytes |
Check error |
|
Raises CalledProcessError |
Timeout |
|
Raises TimeoutExpired |
Working dir |
|
Run in specific directory |
Environment |
|
Custom environment |
Split command |
|
Safe string to list |
Exercises to Complete
-
[ ] Write function to ping host and return True/False
-
[ ] Run
ip addrand parse output for IP addresses -
[ ] Execute command with timeout and retry logic
-
[ ] Build a wrapper for
netapi ise mnt sessions
Next Session
Session 06: Infrastructure - HTTP, argparse, config, logging.
Session Log
| Timestamp | Notes |
|---|---|
Start |
<Record when you started> |
End |
<Record when you finished> |