Python Virtual Environments & pip Cheat Sheet
Covers creating and activating virtual environments with venv, installing and pinning packages with pip, and managing requirements files.
Creating & Activating a venv
Create isolated Python environments with the built-in venv module.
python3 -m venv .venv # Create virtual environmentsource .venv/bin/activate # Activate (macOS/Linux).venv\Scripts\activate # Activate (Windows cmd).venv\Scripts\Activate.ps1 # Activate (Windows PowerShell)deactivate # Exit the virtual environmentwhich python # Confirm interpreter path (should point to .venv)
Installing & Managing Packages
Core pip commands for installing, upgrading, and removing packages.
pip install requests # Install latest versionpip install requests==2.31.0 # Install exact versionpip install "requests>=2.28,<3" # Install with version rangepip install -U requests # Upgrade to latestpip uninstall requests # Remove a packagepip list # List installed packagespip show requests # Show package detailspip list --outdated # Show packages with newer versions available
requirements.txt Workflow
Freeze and restore dependencies for reproducible environments.
pip freeze > requirements.txt # Snapshot installed packagespip install -r requirements.txt # Install from filepip install -r requirements-dev.txt # Install dev-only extraspip install --upgrade -r requirements.txt # Upgrade all pinned packages
Useful pip Flags
Handy flags for common pip workflows.
- -e .- Install the current directory in editable/development mode (uses setup.py or pyproject.toml)
- --no-cache-dir- Skip pip's package cache, useful in Docker builds to reduce image size
- --index-url- Install from a custom package index instead of PyPI
- --no-deps- Install a package without pulling in its dependencies
- -r <file>- Install packages listed in a requirements file
- pip check- Verify installed packages have compatible dependency versions
- pip cache purge- Clear pip's local wheel/package cache
pyproject.toml & Editable Installs (PEP 517/660)
Modern projects declare their build backend in pyproject.toml instead of setup.py.
[build-system]requires = ["setuptools>=68", "wheel"]build-backend = "setuptools.build_meta"[project]name = "myapp"version = "0.1.0"dependencies = [ "requests>=2.28,<3", "click>=8.1",][project.optional-dependencies]dev = ["pytest>=7", "ruff", "mypy"]# pip install -e . installs in editable mode via PEP 660# pip install -e ".[dev]" installs the dev extras too# No setup.py required — setuptools reads this file directly
Deterministic Locking with pip-tools
Separate loose top-level deps from a fully pinned, hash-verified lockfile.
pip install pip-tools# requirements.in — only direct, unpinned dependenciesecho "django>=5.0" > requirements.inpip-compile requirements.in # Resolve -> requirements.txt (pinned + hashes optional)pip-compile --generate-hashes requirements.in # Add --hash lines for supply-chain verificationpip-sync requirements.txt # Make the venv match the lockfile EXACTLY (installs/removes)pip-compile --upgrade-package django requirements.in # Bump one package, keep others pinned
Custom Indexes, Constraints & Config Files
Route installs through a private index and pin transitive versions without listing them as direct deps.
# pip.conf / pip.ini (per-venv: <venv>/pip.conf)# [global]# index-url = https://pypi.company.internal/simple# extra-index-url = https://pypi.org/simple# timeout = 60pip install -c constraints.txt -r requirements.txt # Cap transitive versions without adding them as depspip download -r requirements.txt -d ./wheelhouse # Pre-fetch wheels for an offline/air-gapped installpip install --no-index --find-links=./wheelhouse -r requirements.txt # Install fully offlinepip config list # Show effective pip configuration & source files
venv Internals & Environment Variables
What activation actually changes, and how to script venv usage without 'activating' at all.
python3 -m venv --without-pip .venv # Skip bootstrapping pip (faster, minimal env)python3 -m venv --upgrade .venv # Repoint venv at a newer patch of the same interpreter# Activation only sets these — no magic beyond it:export VIRTUAL_ENV="$PWD/.venv"export PATH="$VIRTUAL_ENV/bin:$PATH"unset PYTHONHOME# Run tools inside a venv WITHOUT activating (great for CI/Makefiles):.venv/bin/python -m pytest.venv/bin/pip install -U pipVIRTUAL_ENV_DISABLE_PROMPT=1 source .venv/bin/activate # Activate without touching PS1
Packaging & Resolver Terminology
Terms that matter once you move past 'pip install' into real dependency management.
- wheel (.whl)- Pre-built binary distribution format; installs are fast because no compilation happens at install time
- sdist- Source distribution; pip falls back to it (and builds from source) when no compatible wheel exists
- manylinux tag- Wheel platform tag signaling glibc compatibility across Linux distros for compiled extensions
- backtracking resolver- pip's dependency resolver (2020+) that can undo earlier choices when a later constraint conflicts
- PEP 621- Standard for declaring project metadata (name, deps, version) directly in pyproject.toml
- PEP 660- Standard enabling editable installs (-e) without a legacy setup.py develop step
- extras (package[extra])- Optional dependency groups, e.g. 'requests[socks]' or 'myapp[dev]'
- hash-checking mode- pip install --require-hashes refuses to install any package whose hash isn't pinned, blocking tampered artifacts
Commit a lockfile-style requirements.txt (or use pip-tools/Poetry) so teammates and CI get identical dependency versions — plain 'pip freeze' output mixes direct and transitive dependencies, which pip-compile keeps separate and reproducible.