/user/kayd @ devops :~$ cat python-basics-cli.md

Python Basics & CLI Cheatsheet Python Basics & CLI Cheatsheet

QR Code linking to: Python Basics & CLI Cheatsheet
Karandeep Singh
Karandeep Singh
• 8 minutes

Summary

Notes on core Python syntax, error handling, file I/O with pathlib, plus the CLI side (venv, pip, argparse, and python -m tricks).

Python shows up in every DevOps job I’ve had, from quick log parsers to full AWS automation. These are the syntax bits and CLI commands I look up most often. For AWS scripting specifically, see my Python Boto3 Cheatsheet.

Variables & Types

Docs: Built-in Types, Python 3 docs

name = "karandeep"          # str
count = 42                  # int
ratio = 0.75                # float
enabled = True              # bool
nothing = None              # NoneType

# Multiple assignment and swap
a, b = 1, 2
a, b = b, a

# Type checks and conversion
isinstance(count, int)      # True
int("42"), str(42), float("0.5"), bool("")   # 42, '42', 0.5, False

Strings & f-strings

Docs: String methods, Python 3 docs

s = "prod-web-01"
s.upper(), s.lower(), s.title()
s.startswith("prod"), s.endswith("01")
s.split("-")                # ['prod', 'web', '01']
"-".join(["prod", "db", "02"])
s.replace("web", "app")
s.strip(), s.lstrip(), s.rstrip()
"web" in s                  # True

# f-strings (use these, always)
env, cpu = "prod", 87.5432
f"{env=}"                   # "env='prod'" - great for debugging
f"{cpu:.2f}%"               # "87.54%"
f"{count:>8}"               # right-align, width 8
f"{1024**3:,}"              # "1,073,741,824"
f"{0.875:.1%}"              # "87.5%"

Lists, Dicts, Sets & Tuples

Docs: Data Structures in the Python tutorial

# list - ordered, mutable
hosts = ["web1", "web2"]
hosts.append("web3"); hosts.extend(["db1"]); hosts.insert(0, "lb1")
hosts.remove("web1"); last = hosts.pop()
hosts[0], hosts[-1], hosts[1:3], hosts[::-1]     # index, last, slice, reverse
sorted(hosts), len(hosts), "db1" in hosts

# tuple - ordered, immutable (good dict keys)
point = ("us-east-1", "a")

# dict - key/value
cfg = {"env": "prod", "replicas": 3}
cfg["env"]; cfg.get("region", "us-east-1")       # .get avoids KeyError
cfg["region"] = "eu-west-1"
cfg.keys(), cfg.values(), cfg.items()
merged = cfg | {"replicas": 5}                    # 3.9+ merge operator
cfg.setdefault("tags", []).append("blue")

# set - unique, unordered
seen = {"web1", "web2"}
seen.add("web3"); seen.discard("web1")
{"a", "b"} & {"b", "c"}     # intersection {'b'}
{"a", "b"} | {"b", "c"}     # union
{"a", "b"} - {"b"}          # difference

Comprehensions

Docs: List comprehensions, Python 3 tutorial

squares = [x * x for x in range(10)]
evens   = [x for x in range(10) if x % 2 == 0]
by_name = {h: len(h) for h in hosts}                 # dict comprehension
unique  = {line.split()[0] for line in log_lines}    # set comprehension
gen     = (x * x for x in range(10**9))              # generator - lazy, no memory blowup
flat    = [x for row in matrix for x in row]         # nested flatten

Functions

Docs: Defining functions, Python 3 tutorial

def deploy(service: str, replicas: int = 1, *, dry_run: bool = False) -> str:
    """Args after * are keyword-only."""
    return f"deploy {service} x{replicas} dry_run={dry_run}"

deploy("api", replicas=3, dry_run=True)

def merge_tags(*args, **kwargs): ...     # variadic positional / keyword
run = lambda cmd: cmd.split()            # small throwaway functions

# Never use a mutable default
def add_host(host, hosts=None):
    hosts = hosts if hosts is not None else []

Classes (briefly)

Docs: Python dataclasses docs

from dataclasses import dataclass, field

@dataclass
class Server:
    name: str
    env: str = "dev"
    tags: list[str] = field(default_factory=list)

    def fqdn(self) -> str:
        return f"{self.name}.{self.env}.example.com"

s = Server("web1", env="prod")
s.fqdn()                     # 'web1.prod.example.com'

Error Handling

Docs: Errors and Exceptions, Python 3 tutorial

try:
    result = 10 / int(value)
except (ValueError, ZeroDivisionError) as e:
    print(f"bad input: {e}")
except Exception:
    raise                    # re-raise unexpected errors - don't swallow them
else:
    print("only runs if no exception")
finally:
    cleanup()                # always runs

# Raise your own, chain the cause
raise RuntimeError("deploy failed") from e

# Context managers handle cleanup for you
with open("app.log") as f, open("out.log", "w") as out:
    out.write(f.read())

File I/O & pathlib

Docs: pathlib on docs.python.org

from pathlib import Path
import json

p = Path("/etc/app/config.json")
p.exists(), p.is_file(), p.is_dir()
p.name, p.stem, p.suffix, p.parent       # config.json, config, .json, /etc/app
p.read_text(), p.write_text("data")
p.read_bytes()

cfg = json.loads(Path("config.json").read_text())
Path("out.json").write_text(json.dumps(cfg, indent=2))

# Build paths with / - no os.path.join
log_dir = Path.home() / "logs" / "app"
log_dir.mkdir(parents=True, exist_ok=True)

# Globbing
for f in Path("/var/log").glob("*.log"): ...
for f in Path(".").rglob("**/*.yaml"): ...       # recursive

# Stream large files line by line
with open("huge.log") as f:
    for line in f:
        if "ERROR" in line:
            print(line, end="")

Dates & Times

Docs: Python datetime docs

from datetime import datetime, timedelta, timezone, date

now_utc = datetime.now(timezone.utc)          # always prefer aware datetimes
today   = date.today()

# Format / parse
now_utc.strftime("%Y-%m-%d %H:%M:%S")         # '2025-05-12 09:15:00'
now_utc.isoformat()                           # '2025-05-12T09:15:00+00:00'
datetime.strptime("2025-05-12", "%Y-%m-%d")
datetime.fromisoformat("2025-05-12T09:15:00+00:00")

# Arithmetic
deadline = now_utc + timedelta(days=7, hours=3)
age = now_utc - datetime(2022, 7, 23, tzinfo=timezone.utc)
age.days, age.total_seconds()

# Epoch conversions (log timestamps, APIs)
now_utc.timestamp()                           # datetime -> epoch float
datetime.fromtimestamp(1752570000, tz=timezone.utc)

# Named zones without third-party libs (3.9+)
from zoneinfo import ZoneInfo
datetime.now(ZoneInfo("America/Edmonton"))

Sorting

Docs: Sorting Techniques, Python 3 HOWTO

nums = [3, 1, 2]
sorted(nums)                        # new list; nums.sort() sorts in place
sorted(nums, reverse=True)

# Sort by a key
hosts = ["web10", "web2", "db1"]
sorted(hosts, key=len)
sorted(hosts, key=str.lower)

# Sort dicts / tuples / objects
servers = [{"name": "web1", "cpu": 80}, {"name": "db1", "cpu": 45}]
sorted(servers, key=lambda s: s["cpu"], reverse=True)

from operator import itemgetter, attrgetter
sorted(servers, key=itemgetter("cpu"))
sorted(instances, key=attrgetter("launch_time"))

# Multi-key: env ascending, then cpu descending
sorted(servers, key=lambda s: (s["env"], -s["cpu"]))

# Top/bottom N without a full sort
import heapq
heapq.nlargest(3, servers, key=itemgetter("cpu"))

# Keep a list sorted while inserting
import bisect
bisect.insort(nums, 2)

Queues, Stacks & Heaps

Docs: collections.deque, Python 3 docs

# deque - O(1) at both ends: stack AND queue
from collections import deque
q = deque(["job1", "job2"])
q.append("job3")           # enqueue right
q.popleft()                # dequeue left  -> FIFO queue
q.pop()                    # pop right     -> LIFO stack
tail = deque(open("app.log"), maxlen=10)   # like tail -n 10

# heapq - priority queue on a plain list
import heapq
pq = []
heapq.heappush(pq, (2, "deploy"))
heapq.heappush(pq, (1, "hotfix"))
heapq.heappop(pq)          # (1, 'hotfix') - smallest priority first

# queue.Queue - thread-safe, for producer/consumer pipelines
from queue import Queue
jobs = Queue()
jobs.put("build"); jobs.get(); jobs.task_done()

The thread-safe queue.Queue matters most once worker pools are involved. Full producer/consumer patterns are in the Python Threading & Concurrency Cheatsheet.

0

URLs & HTTP

Docs: urllib.request on docs.python.org

# Parse and build URLs
from urllib.parse import urlparse, urlencode, quote, parse_qs
u = urlparse("https://api.example.com/v1/deploy?env=prod&tag=v2")
u.scheme, u.netloc, u.path       # 'https', 'api.example.com', '/v1/deploy'
parse_qs(u.query)                # {'env': ['prod'], 'tag': ['v2']}
urlencode({"env": "prod", "app": "my api"})   # 'env=prod&app=my+api'
quote("path with spaces")                     # 'path%20with%20spaces'

# GET JSON - stdlib only, no dependencies
import json, urllib.request
with urllib.request.urlopen("https://api.github.com/zen", timeout=10) as r:
    body = r.read().decode()
    r.status, r.headers["Content-Type"]

# POST JSON
req = urllib.request.Request(
    "https://api.example.com/v1/deploy",
    data=json.dumps({"env": "prod"}).encode(),
    headers={"Content-Type": "application/json", "Authorization": "Bearer TOKEN"},
    method="POST",
)
with urllib.request.urlopen(req, timeout=10) as r:
    result = json.load(r)

For anything beyond a quick script, just pip install requests and get sessions, retries, and connection pooling with far less ceremony.

1

CLI: Interpreter Flags

Docs: Command line and environment, Python 3 docs

2
CommandWhat it does
python -c "print(1+1)"Run a one-liner
python -i script.pyRun script, then drop into REPL with its state
python -m moduleRun a module as a script (uses your venv’s version)
python -u script.pyUnbuffered stdout, needed in containers/CI logs
python -X dev script.pyDev mode: extra warnings, asyncio debug
python -V / python -VVVersion / verbose version
python -qREPL without the banner

CLI: Useful -m Modules

Docs: The -m option, Python 3 docs

3
python -m http.server 8000              # instant file server in cwd
python -m json.tool < data.json         # pretty-print / validate JSON
python -m venv .venv                    # create virtualenv
python -m pip install requests          # pip tied to *this* interpreter
python -m site                          # show sys.path and site-packages
python -m timeit "'-'.join(map(str, range(100)))"
python -m calendar 2026
python -m zipfile -c out.zip src/       # create a zip
python -m tarfile -e release.tar.gz     # extract a tarball
python -m unittest discover             # run tests
python -m pdb script.py                 # step-through debugger

venv & pip

Docs: Python venv docs

4
python -m venv .venv
source .venv/bin/activate               # Linux/macOS
.venv\Scripts\activate                  # Windows
deactivate

pip install requests boto3              # install
pip install -r requirements.txt         # from file
pip install -e .                        # editable local package
pip install 'urllib3<2'                 # version constraint
pip list --outdated
pip show requests                       # version, deps, location
pip freeze > requirements.txt           # pin exact versions
pip uninstall -y requests

argparse Skeleton

Docs: Python argparse docs

5
#!/usr/bin/env python3
import argparse

def main() -> None:
    parser = argparse.ArgumentParser(description="Deploy helper")
    parser.add_argument("service", help="service name")
    parser.add_argument("-e", "--env", default="dev", choices=["dev", "staging", "prod"])
    parser.add_argument("-r", "--replicas", type=int, default=1)
    parser.add_argument("--dry-run", action="store_true")
    parser.add_argument("-v", "--verbose", action="count", default=0)
    args = parser.parse_args()

    print(f"deploying {args.service} to {args.env} x{args.replicas}")

if __name__ == "__main__":
    main()
./deploy.py api -e prod -r 3 --dry-run
./deploy.py --help                      # auto-generated help

Scripting Essentials

Docs: Python subprocess docs

import sys, os, subprocess

sys.argv                                 # raw CLI args
sys.exit(1)                              # non-zero = failure, scripts should use it
os.environ.get("AWS_REGION", "us-east-1")

# Run shell commands - capture output, raise on failure
result = subprocess.run(
    ["git", "rev-parse", "--short", "HEAD"],
    capture_output=True, text=True, check=True,
)
sha = result.stdout.strip()

When a script outgrows a single loop and needs parallel downloads or API calls, jump to the Python Threading & Concurrency Cheatsheet.

6
  • Python Threading & Concurrency: Thread, Lock, ThreadPoolExecutor, and asyncio, with a decision table for I/O-bound vs CPU-bound work
  • Python Boto3: S3, EC2, Lambda, and DynamoDB automation built on this page’s syntax (sessions, paginators, waiters)
  • Bash Basics: the other scripting language on every box, with parameter expansion, tests, traps, and arrays

The rest of my Python notes live in the Python group, and everything else is in the cheatsheet library.

Similar Articles

More from development

Go (Golang) Cheatsheet

Go cheatsheet covering the go toolchain, syntax essentials, goroutines and channels, table-driven …

Bash Basics Cheatsheet

Quick-reference Bash basics cheatsheet: variables, parameter expansion, conditionals, loops, arrays, …

Python Boto3 Cheatsheet

Boto3 cheatsheet for AWS automation: sessions, S3, EC2, Lambda, DynamoDB, SSM, presigned URLs, …