Stage 7 · Master
Python for Operators
Virtual Environments & pip
venv, pip, requirements.txt, pyproject.toml, and dependency pinning.
Why Isolation Matters
System Python is shared across your entire OS. Installing packages globally risks breaking system tools that depend on specific versions. Virtual environments give each project its own isolated Python interpreter and package directory.
Every pip install should go into a virtual environment. No exceptions. This prevents version conflicts between projects and keeps your system Python clean.
venv — The Standard
# Create a venv
python3 -m venv .venv
# Activate (macOS/Linux)
source .venv/bin/activate
# Verify isolation
which python3 # Should show .venv/bin/python3
python3 -c "import sys; print(sys.prefix)" # Should show .venv path
# Install packages (only affects this venv)
pip install requests pyyaml httpx
# Deactivate
deactivate
# Remove a venv
rm -rf .venv/The .venv directory contains a complete Python environment: interpreter, pip, and all installed packages. It is safe to delete and recreate at any time.
pip Basics
# Install a specific version
pip install requests==2.31.0
# Install with version constraints
pip install "requests>=2.28,<3.0"
# Upgrade a package
pip install --upgrade requests
# Show installed packages
pip list
pip show requests
# Uninstall
pip uninstall requests
# Install from a requirements file
pip install -r requirements.txt
# Export installed packages
pip freeze > requirements.txtpip freeze outputs all installed packages with their exact versions. This is how you create reproducible environments.
requirements.txt
# Exact versions (from pip freeze)
requests==2.31.0
pyyaml==6.0.1
httpx==0.27.0
# Version constraints
urllib3>=2.0,<3.0
certifi>=2023.7.22
# Install from git
git+https://github.com/user/repo.git@main
# Local editable install (for development)
-e ./libs/my-common-librequirements.txt with pinned versions ensures every developer and CI runner installs the same versions. Unpinned dependencies can cause 'works on my machine' issues.
Use a requirements-dev.txt for testing and linting tools. Never include dev tools in your production requirements. This keeps production images small and reduces attack surface.
pyproject.toml
pyproject.toml is the modern standard for Python project configuration. It replaces setup.py, setup.cfg, and multiple config files with a single TOML file.
[project]
name = "my-devops-tool"
version = "1.0.0"
description = "Operational tooling for production"
requires-python = ">=3.10"
dependencies = [
"requests>=2.28,<3.0",
"pyyaml>=6.0",
"httpx>=0.24",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"pytest-cov>=4.0",
"ruff>=0.1.0",
"mypy>=1.0",
]
[tool.ruff]
line-length = 100
[tool.mypy]
strict = truepyproject.toml is parsed by pip, poetry, pdm, and hatch. It is the single source of truth for your project's metadata and dependencies.
Dependency Pinning
| Approach | Pros | Cons |
|---|---|---|
| pip freeze (requirements.txt) | Simple, universal, reproducible | No dependency resolution |
| pyproject.toml + uv | Fast, modern, lockfile support | Newer tooling |
| Poetry | Lockfile, dependency groups | Heavy, opinionated |
| pip-tools | Compile constraints, hash checking | Extra step |
# Install pip-tools
pip install pip-tools
# Create a constraints file from pyproject.toml
pip-compile pyproject.toml
# This generates requirements.txt with exact versions and hashes
# Install from the compiled file
pip install -r requirements.txt
# Update all dependencies
pip-compile --upgrade pyproject.tomlpip-compile resolves the full dependency tree and pins every package with a hash. This ensures bit-for-bit reproducible installs.
uv is a drop-in replacement for pip written in Rust. It is 10-100x faster for large dependency sets. Install with pip install uv, then use it like pip.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.