Lesson 01 of 9 · Modules
Python essentials for ops people
Python for people who already live in a terminal: set up a virtual environment, then learn the core language (values, lists, dictionaries, loops, functions, f-strings and exceptions) through ops-flavoured examples.
Why Python after Bash
Bash is perfect for gluing commands together. When a script needs data structures, error handling, APIs, tests or more than a page of logic, Python is easier to write, read and maintain. Ansible, many Kubernetes operators, cloud CLIs and most infrastructure tooling are written in it.
Bash is like giving someone quick instructions by walkie-talkie: fast, but hard to do anything complicated. Python is like writing a proper plan in a notebook: lists, tables, "if this goes wrong, do that", and it's easy for the next person to read.
Set up a project
$ mkdir ops-tools && cd ops-tools
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) $ pip install requests pyyaml
(.venv) $ python --version
Python 3.12.3
Always work inside a venv. Installing packages into the system Python can break OS tools (many distributions now refuse pip install system-wide for this reason).
Values and types
host = "web-01" # str
port = 8080 # int
load = 0.73 # float
healthy = True # bool
nothing = None # "no value"
print(type(port), port + 1) # <class 'int'> 8081
print(f"{host}:{port} load={load:.0%}") # web-01:8080 load=73%
Lists and dictionaries: the two structures you'll use most
hosts = ["web-01", "web-02", "db-01"]
hosts.append("cache-01")
print(hosts[0], len(hosts)) # web-01 4
server = {"name": "web-01", "ip": "10.0.5.20", "roles": ["web", "api"]}
print(server["ip"]) # 10.0.5.20
print(server.get("zone", "unknown")) # unknown (no KeyError)
server["zone"] = "eu-1a"
Real infrastructure data (JSON from APIs, YAML configs, kubectl output) is just nested lists and dictionaries.
Loops and conditions
servers = [
{"name": "web-01", "disk_pct": 91},
{"name": "web-02", "disk_pct": 40},
{"name": "db-01", "disk_pct": 83},
]
for s in servers:
if s["disk_pct"] >= 90:
print(f"CRITICAL {s['name']} {s['disk_pct']}%")
elif s["disk_pct"] >= 80:
print(f"WARNING {s['name']} {s['disk_pct']}%")
full = [s["name"] for s in servers if s["disk_pct"] >= 80] # list comprehension
print(full) # ['web-01', 'db-01']
Functions
def classify(pct: int, warn: int = 80, crit: int = 90) -> str:
"""Return OK, WARNING or CRITICAL for a usage percentage."""
if pct >= crit:
return "CRITICAL"
if pct >= warn:
return "WARNING"
return "OK"
print(classify(85)) # WARNING
print(classify(85, warn=90)) # OK
Type hints (pct: int, -> str) are optional, but they document intent and let editors catch mistakes.
Errors: exceptions
from pathlib import Path
def read_config(path: str) -> str:
try:
return Path(path).read_text()
except FileNotFoundError:
print(f"config {path} not found, using defaults")
return ""
except PermissionError:
raise SystemExit(f"cannot read {path}: permission denied")
Catch specific exceptions you can handle; let unexpected ones surface with a full traceback. That's a feature, not a failure.
Try it: disk report in Python
- Create a venv and a file
disk_report.py. - Use
shutil.disk_usage("/")to get total/used/free bytes and compute the used percentage. - Put three mount points in a list (e.g.
["/", "/var", "/tmp"]), loop over them, and printOK/WARNING/CRITICALwith theclassifyfunction. Skip paths that don't exist (Path(p).exists()). - Print the results as an aligned table with f-strings (
f"{mount:<10} {pct:>5.1f}%").
Going deeper: habits from day one
- Follow PEP 8 style; let
ruff(linter and formatter) enforce it automatically. - Put code in functions and use
if __name__ == "__main__": main()so files can be imported and tested (lesson 08). - Prefer
pathlib.Pathover string paths, and theloggingmodule overprintonce a tool is more than a quick script (lesson 05). - Pin dependencies (
requirements.txtorpyproject.toml) so a tool behaves the same next year.
Recap
- Always use a venv; install with
pip, record withpip freeze. - Core types:
str,int,float,bool,None; structures: lists and dicts (nest them freely). for,if/elif/else, comprehensions, functions with defaults and type hints, f-strings.- Handle specific exceptions; let the rest fail loudly.
This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.