DevOps · Python
Why Every DevOps Engineer Should Learn Python in 2026
Quick summary — why DevOps engineers should learn Python
DevOps engineers should learn Python in 2026 because it handles what Bash struggles with: readable automation with proper error handling, cloud SDKs such as boto3 for audits and clean-ups, API integrations with chat and ticket tools, tests for scripts and infrastructure and small command-line tools teammates can maintain.
In this guide you will learn:
- When to choose Python — over Bash.
- Cloud automation — with SDKs.
- API integrations — and webhooks.
- Testing your tools — with pytest.
- Interview questions — on Python for DevOps.
SECTION 01When to choose Python over Bash
Bash remains essential for quick commands, glue in pipelines and small setup scripts. Python becomes the better choice as scripts grow: when you need data structures, JSON handling, retries, clear error messages, tests or reuse across a team. Many DevOps teams follow a simple rule: if a script is getting long or complex, rewrite it in Python:
| Situation | Bash | Python | Better choice |
|---|---|---|---|
| Run a few commands in order | Simple and fast | More setup | Bash |
| Parse JSON from an API | Needs jq and care | Built-in json module | Python |
| Retry on failure with backoff | Awkward | Clear loop or library | Python |
| Tool used by the whole team | Hard to test | Functions, tests, CLI | Python |
#!/usr/bin/env bash
# Check that services respond; fine while it stays small
set -u
for url in https://example.com https://example.org; do
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 "$url")
if [ "$code" = "200" ]; then
echo "OK $url"
else
echo "FAIL $url ($code)"
fi
done
# pip install requests
import sys
import time
import requests
URLS = ["https://example.com", "https://example.org"]
def check(url: str, retries: int = 3) -> bool:
for attempt in range(1, retries + 1):
try:
r = requests.get(url, timeout=5)
if r.status_code == 200:
return True
except requests.RequestException as err:
print(f" attempt {attempt} failed: {err}")
time.sleep(2 ** attempt) # backoff: 2s, 4s, 8s
return False
failed = [u for u in URLS if not check(u)]
for u in URLS:
print(("FAIL " if u in failed else "OK ") + u)
sys.exit(1 if failed else 0)
SECTION 02Cloud automation with SDKs
Cloud providers publish Python SDKs, such as boto3 for AWS, that let you list, create, tag and clean up resources in code. Typical DevOps tasks include auditing security settings across all buckets, finding untagged resources, stopping development instances at night and generating inventory reports. Python's paginators and error handling make these scripts reliable even across many resources:
| Task | SDK feature | Why Python helps | Safety tip |
|---|---|---|---|
| Audit bucket settings | List and get configuration | Loop and collect results | Read-only permissions |
| Find untagged resources | Describe calls + tags | Dictionaries for tags | Report before acting |
| Stop dev instances at night | Filter and stop | Scheduled and logged | Use a dry-run mode |
| Inventory report | Paginators | Handles many pages | Export to CSV |
# pip install boto3 Needs read-only S3 permissions
import boto3
from botocore.exceptions import ClientError
s3 = boto3.client("s3")
for b in s3.list_buckets()["Buckets"]:
name = b["Name"]
try:
cfg = s3.get_public_access_block(Bucket=name)["PublicAccessBlockConfiguration"]
blocked = all(cfg.values())
except ClientError as err:
if err.response["Error"]["Code"] == "NoSuchPublicAccessBlockConfiguration":
blocked = False
else:
raise
print(f"{'OK ' if blocked else 'WARN'} {name}")
# Stops running instances tagged env=dev; dry run by default
import argparse
import boto3
parser = argparse.ArgumentParser()
parser.add_argument("--apply", action="store_true", help="actually stop instances")
args = parser.parse_args()
ec2 = boto3.client("ec2", region_name="ap-south-1")
ids = []
for page in ec2.get_paginator("describe_instances").paginate(
Filters=[{"Name": "tag:env", "Values": ["dev"]},
{"Name": "instance-state-name", "Values": ["running"]}]):
for r in page["Reservations"]:
ids += [i["InstanceId"] for i in r["Instances"]]
print("would stop:" if not args.apply else "stopping:", ids)
if args.apply and ids:
ec2.stop_instances(InstanceIds=ids)
SECTION 03API integrations and testing your tools
DevOps work connects many systems: chat tools for alerts, ticket systems for incidents, CI tools and monitoring APIs. Python's requests library makes these integrations short and readable. As your tools grow, add tests with pytest, so changes do not break automation that the team depends on. Testing also makes interviews easier, because you can show working, verified code:
| Integration | Example | Python tool | Good practice |
|---|---|---|---|
| Chat alert | Post a message to a webhook | requests.post | Webhook URL from environment |
| Ticket creation | Open an incident ticket | Tool's REST API | Handle errors and timeouts |
| CI status | Read workflow results | CI API or CLI | Paginate results |
| Script tests | Check logic without real APIs | pytest + mocks | Test edge cases |
# pip install requests
import os
import requests
def notify(text: str) -> bool:
url = os.environ.get("CHAT_WEBHOOK_URL")
if not url:
print("no webhook configured; message:", text)
return False
try:
r = requests.post(url, json={"text": text}, timeout=5)
r.raise_for_status()
return True
except requests.RequestException as err:
print("notification failed:", err)
return False
if __name__ == "__main__":
notify("Deploy to staging finished: version 1.4.2")
# test_notify.py Run: pytest -q
from unittest.mock import patch, MagicMock
import notify as n # the module from the previous tab saved as notify.py
def test_returns_false_without_webhook(monkeypatch):
monkeypatch.delenv("CHAT_WEBHOOK_URL", raising=False)
assert n.notify("hi") is False
def test_posts_json(monkeypatch):
monkeypatch.setenv("CHAT_WEBHOOK_URL", "https://chat.example/hook")
fake = MagicMock()
fake.raise_for_status.return_value = None
with patch("notify.requests.post", return_value=fake) as post:
assert n.notify("deployed") is True
post.assert_called_once()
assert post.call_args.kwargs["json"] == {"text": "deployed"}
SECTION 04Python for DevOps learning plan
Use these templates to learn Python with DevOps-focused practice:
Week 1 Python basics: types, functions, dicts, lists, files
Week 2 subprocess, pathlib, argparse; exit codes
Week 3 JSON, YAML and requests; error handling and retries
Week 4 Cloud SDK (boto3): list, tag, report; dry-run patterns
Week 5 pytest and mocking; packaging a small CLI
Week 6 Project: an ops tool used in a CI pipeline
Project: ops-toolkit CLI
Commands:
ops audit-buckets report bucket public access settings
ops untagged list resources missing team/env tags
ops stop-dev --apply stop dev instances (dry run by default)
ops notify "message" post to a chat webhook
Includes: argparse CLI, logging, pytest tests with mocks,
GitHub Actions workflow running tests, README with examples
import argparse
import logging
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
def main() -> None:
parser = argparse.ArgumentParser(prog="ops")
sub = parser.add_subparsers(dest="command", required=True)
sub.add_parser("untagged", help="list untagged resources")
stop = sub.add_parser("stop-dev", help="stop dev instances")
stop.add_argument("--apply", action="store_true")
args = parser.parse_args()
logging.info("running %s", args.command)
if __name__ == "__main__":
main()
SECTION 05Tips for DevOps engineers learning Python
These habits make your Python tools reliable:
- Rewrite long Bash in Python — complexity is easier to manage.
- Default to dry runs — require a flag to make changes.
- Use timeouts everywhere — network calls should never hang.
- Keep secrets in the environment — never hard-code tokens.
- Test with mocks — verify logic without touching real systems.
SECTION 06Interview Q&A — Python for DevOps
Q1When would you use Python instead of Bash?
When a script needs data structures, JSON or API handling, retries, clear error handling, tests or long-term maintenance by a team.
Q2How do you run shell commands from Python safely?
Use subprocess.run with a list of arguments, check=True and timeouts, and avoid shell=True with user input.
Q3What is pagination in cloud SDKs and why does it matter?
APIs return results in pages; using paginators ensures you process all resources, not just the first page.
Q4How do you handle secrets in automation scripts?
Read them from environment variables or a secrets manager at runtime and never commit them to code or logs.
Q5How do you test a script that calls external APIs?
Separate logic into functions and use mocks to replace API calls in tests, checking inputs and handling of responses and errors.
SECTION 07Test yourself — Python for DevOps quiz
Five questions. No sign-up.
0 / 5Pick an answer to see why it is right or wrong.
SECTION 08Frequently asked questions
Do DevOps engineers need Python?
Python is not always required, but it appears in many DevOps listings and is very useful for automation, cloud SDKs, integrations and tooling.
Should I learn Bash or Python first for DevOps?
Learn basic Bash first for daily Linux work, then add Python as your automation needs grow. Both are valuable.
How much Python does a DevOps engineer need?
Core syntax, functions, data structures, files, JSON, requests, subprocess, error handling, a cloud SDK and basic testing cover most needs.
Is Go replacing Python in DevOps?
Go is used for many infrastructure tools, but Python remains widely used for scripts and automation. Read listings to see what teams ask for.
What Python project suits a DevOps portfolio?
A small ops CLI with commands for audits, untagged resources and notifications, including dry-run mode, tests with mocks and a CI workflow.
SECTION 09Related reads
Classroom & online · Noida
Build DevOps automation skills
Our DevOps Training Course covers Linux, scripting, Git, CI/CD, Docker, Kubernetes, cloud and Terraform with hands-on automation labs.
Talk to a counsellor for current fees- Scripting and automation
- CI/CD pipelines
- Cloud and Kubernetes
- Weekday & weekend batches