D

Python

Python essentials for DevOps scripting — environments, packaging, and common automation patterns.

Updated 2026-09-03

On this page

Python shows up in DevOps as the glue between CLIs — automation scripts, Lambda handlers, Ansible modules, CI tooling. This page covers the environment and stdlib patterns you reach for constantly, not the language itself.

Version & REPL

python3 --version

Prints the installed Python version.

python3 -m venv .venv

Creates an isolated virtual environment in .venv, so project dependencies don't leak into or clash with the system Python.

source .venv/bin/activate

Activates a virtual environment in the current shell — installed packages and the python/pip commands now resolve inside it.

deactivate

Exits the active virtual environment, returning to the system (or previously active) Python.

Packaging (pip)

pip install requests

Installs a package into the active environment.

pip install -r requirements.txt

Installs every package pinned in a requirements file.

pip freeze > requirements.txt

Writes every installed package and its exact version to a requirements file, for a reproducible environment.

pip list --outdated

Shows installed packages that have a newer version available.

Pin your dependencies

pip freeze output pins exact versions transitively too — commit it for applications (reproducibility) but use looser ranges in a library's own pyproject.toml so it doesn't force conflicting pins on whoever depends on it.

Running Scripts

python3 script.py

Runs a script with the active interpreter.

python3 -m module_name

Runs an installed module as a script — resolves via sys.path rather than a file path, and is how you invoke most CLI tools distributed as Python packages (python3 -m pytest, python3 -m http.server).

python3 -c 'import sys; print(sys.path)'

Runs a one-line inline script — handy for quick checks without a file.

Formatting & Linting

black .

Auto-formats every Python file in the current directory to a consistent style.

ruff check .

Lints the codebase for errors and style issues; fast enough to run on every save or in CI without noticeable delay.

mypy .

Type-checks the codebase against its type hints, catching a class of bugs before runtime.

Working with Files

from pathlib import Path
 
for path in Path("/var/log/app").glob("*.log"):
    if path.stat().st_size > 100_000_000:
        print(f"{path}: {path.stat().st_size / 1e6:.1f} MB")
import json
 
with open("config.json") as f:
    config = json.load(f)
 
config["retries"] = 3
 
with open("config.json", "w") as f:
    json.dump(config, f, indent=2)

Running Shell Commands (subprocess)

import subprocess
 
result = subprocess.run(
    ["kubectl", "get", "pods", "-o", "json"],
    capture_output=True,
    text=True,
    check=True,
)
print(result.stdout)

Avoid shell=True with untrusted input

subprocess.run(cmd, shell=True) passes the string through a real shell — if any part of cmd comes from outside your own code (an argument, an API payload, an env var), that's a command injection vulnerability. Pass a list of arguments (as above) instead; it never invokes a shell at all.

Environment Variables & Args

import os
import argparse
 
api_key = os.environ["API_KEY"]  # raises KeyError if unset — fail loudly on missing config
timeout = os.environ.get("TIMEOUT", "30")  # falls back to a default instead
 
parser = argparse.ArgumentParser()
parser.add_argument("--env", required=True, choices=["dev", "staging", "prod"])
parser.add_argument("--dry-run", action="store_true")
args = parser.parse_args()

Virtual Environments vs. Docker

venv

Isolates Python packages only — same OS, same system libraries, same Python interpreter version as whatever's installed. Fast to create, cheap to throw away, but doesn't reproduce the runtime environment itself.

Docker

Isolates the entire runtime — OS packages, system libraries, and a pinned Python version, not just pip packages. The right choice once "works on my machine" needs to mean the OS layer too, not just dependencies.

Official documentation

Related