pip — Install, upgrade, and remove Python packages from PyPI across all 5 shells
Equivalents in every shell
pip install requestsShips with Python ≥ 3.4 (as `python -m pip`) and standalone via the OS package manager. Core verbs: `pip install <pkg>` (latest from PyPI), `pip install <pkg>==1.2.3` (pinned version), `pip install -r requirements.txt` (bulk install from a file), `pip install -e .` (editable install of a local project for development), `pip uninstall <pkg>`, `pip list` (installed in the active environment), `pip show <pkg>` (metadata + dep tree node), `pip freeze` (machine-readable `pkg==ver` list for requirements.txt), `pip install -U <pkg>` (upgrade). Strong recommendation: use `python -m pip install ...` instead of bare `pip install ...` — guarantees the pip you call matches the python you're using (multiple Python versions on one machine is the #1 source of "I installed it but it's not found" bugs).
pip install requestsSame external — Python is the same on macOS / Linux / zsh; pip is part of the Python install. macOS-specific: starting in macOS 12.3, system Python 2.7 was removed AND `pip install` against system Python 3 is blocked by PEP 668 (`error: externally-managed-environment`) — Apple wants you to use a venv. The correct macOS pattern is `python3 -m venv .venv; source .venv/bin/activate; pip install requests`. Or use `pipx` (`brew install pipx`) for CLI-tool installs — `pipx install black` installs each tool in its own isolated venv but exposes the executable globally.
pip install requestsSame external. Fish venv activation: `python -m venv .venv; source .venv/bin/activate.fish` — the `.fish` activator is generated by venv automatically. Once activated, `pip install requests` works as in bash. Fish-specific tip for venv discoverability: install `direnv` (`brew install direnv`) + `echo "layout python" > .envrc` — fish auto-activates the venv on `cd` into the project, deactivates on `cd` out. Without something like direnv, you'll forget which venv is active and `pip install` into the wrong env.
pip install requestsPip works IDENTICALLY on Windows pwsh once Python is installed (`winget install Python.Python.3.12`). The Windows-specific quirks are: (1) `python` may resolve to the Microsoft Store "Python redirector" stub on a fresh Win10/11 — the stub launches the Store, doesn't run Python; remove from `Settings → Apps → App execution aliases`; (2) `pip install` on Win-installed Python 3.11+ is NOT PEP 668-restricted (Microsoft's Python build doesn't set `EXTERNALLY-MANAGED`), so `pip install requests` works against the system Python without a venv — but venvs are still the right answer; (3) PowerShell venv activation: `.\.venv\Scripts\Activate.ps1` (note the `.ps1`, not `.fish` or no-extension). Execution policy may block — `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser` once.
pip install requestsIdentical CLI to other platforms — once Python is on `PATH`, `pip install <pkg>` works from cmd. Venv activation in cmd: `.venv\Scripts\activate.bat` (the `.bat`, not `.ps1`). Common Windows footgun: multiple Python installs on `PATH` and `pip` calls one while `python` calls another — `where python` + `where pip` show the resolution order. Always prefer `python -m pip install ...` to lock pip to the same Python `where python` resolves.
Worked examples
Install a package and freeze the result to requirements.txt
pip install requests && pip freeze > requirements.txtpip install requests; and pip freeze > requirements.txtpip install requests; pip freeze | Out-File -Encoding utf8 requirements.txtpip install requests && pip freeze > requirements.txtCreate + activate a venv, install pinned deps
python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txtpython -m venv .venv; and source .venv/bin/activate.fish; and pip install -r requirements.txtpython -m venv .venv; .\.venv\Scripts\Activate.ps1; pip install -r requirements.txtpython -m venv .venv && .venv\Scripts\activate.bat && pip install -r requirements.txtShow outdated packages, upgrade one
pip list --outdated && pip install -U requestspip list --outdated; and pip install -U requestspip list --outdated; pip install -U requestspip list --outdated && pip install -U requestsGotchas
- PEP 668 (`error: externally-managed-environment`) lands on most Linux distros and macOS since 2023 — `pip install` against system Python is BLOCKED. The error message points at venv as the right answer: `python -m venv .venv && source .venv/bin/activate && pip install <pkg>`. Two escape hatches that work but you shouldn't use: `pip install --break-system-packages <pkg>` (overrides PEP 668, may break system tools that depend on specific package versions) and `pip install --user <pkg>` (installs to `~/.local/`, sometimes blocked too). The correct workflow is venvs per project + `pipx` for global CLI tools.
- Bare `pip install <pkg>` calls the FIRST `pip` on PATH, which may NOT match the `python` you run scripts with. Classic bug: `pip install requests` succeeds, then `python myscript.py` fails with `ModuleNotFoundError: No module named requests` — because `pip` was Python 3.10's and `python` is Python 3.11's. Always: `python -m pip install <pkg>` (use the pip that ships with the python you mean to run). Same fix on Windows: `python -m pip install <pkg>` instead of bare `pip`.
- Venv activation has DIFFERENT activator scripts per shell: bash/zsh use `source .venv/bin/activate`; fish uses `source .venv/bin/activate.fish`; pwsh uses `.\.venv\Scripts\Activate.ps1` (Windows) or `.venv/bin/Activate.ps1` (Linux/macOS pwsh); cmd uses `.venv\Scripts\activate.bat`. A bash-style activate command from a fish prompt produces silent garbage — fish parses the bash script as fish syntax, doesn't error, but the venv isn't activated. Always use the activator matching your shell.
- `pip freeze > requirements.txt` captures the FULL transitive dep tree pinned to exact versions — including transitive deps you didn't directly install. This is good for reproducibility (CI installs the exact same versions) but bad for human review (the file lists 50 packages when you actually installed 3). The modern alternative is `pip-tools` (`pip install pip-tools`, then `pip-compile requirements.in` produces `requirements.txt`) or `poetry` / `uv` (which separate "what you asked for" from "what got installed") — `requirements.in` lists your direct deps, `requirements.txt` is the locked transitive set.
- Pip's dependency resolver (since 20.3, late 2020) is "real" — it backtracks when version constraints conflict, producing better error messages than the old "first match wins" resolver. But backtracking can be SLOW on big requirement files (`pip install -r requirements.txt` taking 5+ minutes is the smell). Mitigations: pin versions in `requirements.txt` (resolver has nothing to search), use `pip install --use-deprecated=legacy-resolver` (faster, but you get the old "may produce incompatible installs" behaviour), or switch to `uv` (`pip install uv; uv pip install -r requirements.txt`) — 10-100× faster Rust-implemented resolver.