Skip to content

Python for DevOps Cheat Sheet

Remember: Python's json.tool module is a built-in JSON pretty-printer with no dependencies: python3 -m json.tool < file.json. The -m flag runs a module as a script — it works with http.server (instant file server), venv (virtual environments), base64, zipfile, and more. Python's stdlib is your Swiss army knife on servers where you cannot install extra tools.

One-Liners

# Pretty-print JSON
python3 -m json.tool < file.json
cat file.json | python3 -m json.tool

# Simple HTTP server
python3 -m http.server 8000

# Base64 encode/decode
python3 -c "import base64; print(base64.b64encode(b'secret').decode())"
python3 -c "import base64; print(base64.b64decode('c2VjcmV0').decode())"

# URL encode
python3 -c "import urllib.parse; print(urllib.parse.quote('hello world'))"

# Generate random password
python3 -c "import secrets; print(secrets.token_urlsafe(32))"

# Timestamp conversion
python3 -c "from datetime import datetime; print(datetime.fromtimestamp(1700000000))"

File Operations (pathlib)

from pathlib import Path

p = Path('/etc/nginx/nginx.conf')
p.exists()                    # Check existence
p.read_text()                 # Read file
p.write_text(content)         # Write file
p.stem                        # 'nginx'
p.suffix                      # '.conf'
p.parent                      # Path('/etc/nginx')

# Find files
list(Path('.').rglob('*.yaml'))       # Recursive glob
list(Path('.').glob('*.py'))          # Current dir only

JSON / YAML Processing

import json
import yaml   # pip install pyyaml

# JSON
data = json.loads('{"key": "val"}')
text = json.dumps(data, indent=2)

with open('f.json') as f:
    data = json.load(f)

# YAML
with open('f.yaml') as f:
    data = yaml.safe_load(f)

# Multi-doc YAML
with open('f.yaml') as f:
    for doc in yaml.safe_load_all(f):
        print(doc)

Subprocess (Run Shell Commands)

import subprocess

# Simple command
r = subprocess.run(['kubectl', 'get', 'pods'], capture_output=True, text=True, check=True)
print(r.stdout)

# With timeout
r = subprocess.run(['helm', 'list'], capture_output=True, text=True, timeout=30)

# Parse JSON output
import json
r = subprocess.run(['kubectl', 'get', 'pods', '-o', 'json'], capture_output=True, text=True)
pods = json.loads(r.stdout)

Never use shell=True with user input — shell injection risk.

Gotcha: subprocess.run() with check=True raises CalledProcessError on non-zero exit codes, which is what you want in scripts (fail fast). Without check=True, a failed command silently returns a result object with returncode != 0, and your script continues as if nothing went wrong. Always use check=True unless you explicitly handle non-zero exits.

HTTP Requests

# stdlib (no dependencies)
import urllib.request, json
resp = urllib.request.urlopen('http://localhost:8080/health')
data = json.loads(resp.read())

# requests library (pip install requests)
import requests
r = requests.get('https://api.example.com/data', headers={'Authorization': 'Bearer tok'})
r.raise_for_status()
data = r.json()

r = requests.post('https://api.example.com/deploy',
    json={'version': 'v2.0', 'env': 'prod'},
    timeout=10)

Default trap: yaml.load() (without Loader argument) is a security vulnerability — it can execute arbitrary Python code embedded in YAML. Always use yaml.safe_load(). Modern PyYAML versions warn about this, but older versions silently allow it. This is a common audit finding in DevOps scripts.

Environment Variables

import os

val = os.environ.get('MY_VAR', 'default')   # With default
val = os.environ['REQUIRED_VAR']             # Raises KeyError if missing

# Boolean from env
debug = os.environ.get('DEBUG', 'false').lower() == 'true'

Kubernetes Client

from kubernetes import client, config  # pip install kubernetes

config.load_kube_config()              # From ~/.kube/config
# config.load_incluster_config()       # Inside a pod

v1 = client.CoreV1Api()
pods = v1.list_namespaced_pod('default')
for p in pods.items:
    print(f"{p.metadata.name}: {p.status.phase}")

Jinja2 Templating

from jinja2 import Template, Environment, FileSystemLoader

# Inline
tmpl = Template("Hello {{ name }}")
print(tmpl.render(name="world"))

# From files
env = Environment(loader=FileSystemLoader('templates/'))
tmpl = env.get_template('deploy.yaml.j2')
print(tmpl.render(replicas=3, image='myapp:v2'))

Common Patterns

# Retry with backoff
import time
def retry(fn, attempts=3, delay=2):
    for i in range(attempts):
        try:
            return fn()
        except Exception as e:
            if i == attempts - 1:
                raise
            time.sleep(delay * (2 ** i))

# Parallel execution
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=5) as pool:
    results = list(pool.map(check_health, services))

# Temp files
import tempfile
with tempfile.NamedTemporaryFile(suffix='.yaml', mode='w', delete=False) as f:
    f.write(yaml_content)
    print(f.name)  # Use the path

Script Boilerplate

#!/usr/bin/env python3
"""Brief description of what this script does."""
import argparse
import sys

def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--env', required=True, choices=['dev', 'prod'])
    parser.add_argument('--dry-run', action='store_true')
    args = parser.parse_args()

    # ... your logic here ...

if __name__ == '__main__':
    main()