Three ways you'll run Python
# 1. One-off, interactive (poke at an idea)
python3
>>> 2 + 2
# 2. A script — the ops workhorse
python3 check_disk.py
# 3. Inline — perfect for pipelines
python3 -c "print('ok')"
Anatomy of an ops script
#!/usr/bin/env python3
"""check_disk.py — warn when a mount is over threshold."""
THRESHOLD = 80 # percent
def main():
usage = 83 # in real life: shutil.disk_usage('/')
if usage > THRESHOLD:
print(f"WARN: disk at {usage}% (threshold {THRESHOLD}%)")
else:
print("OK")
if __name__ == "__main__":
main()
Line by line: the shebang (#!/usr/bin/env python3) lets the file run directly after chmod +x. The docstring tells the next engineer (usually future-you) what this does. Constants live at the top. The if __name__ == "__main__" guard means the file can also be imported without side effects — the difference between a script and a reusable tool.
Virtual environments — why every team insists
python3 -m venv .venv # create an isolated environment
source .venv/bin/activate # enter it (prompt changes)
pip install requests boto3 # deps land HERE, not system-wide
pip freeze > requirements.txt # pin what you used
deactivate
Two scripts on one server needing different library versions is a Tuesday. Venvs make each script carry its own dependencies, so upgrading one never breaks another. Rule of thumb: never pip install into the system Python on a server.
Reading errors (the skill that halves your debugging time)
Traceback (most recent call last):
File "check_disk.py", line 9, in main
if usage > THRESHOLD:
TypeError: '>' not supported between instances of 'str' and 'int'
Read tracebacks bottom-up: the last line names the error and why; the lines above show where. Here a string is being compared to a number — someone read the usage from a file and forgot int().