skip to content

pip — Python Package Installer

Complete pip reference covering installation, package management, requirements files, private registries, caching, offline installs, and reproducible builds.

9 min read 47 snippets deep dive

pip#

What it is#

pip is the standard package installer for Python. It has shipped bundled with Python since version 3.4 and installs packages from PyPI (the Python Package Index) by default. pip understands version specifiers (==, >=, ~=, !=), extras (package[extra]), editable installs (-e), and requirements files, making it the lowest-common-denominator tool that every Python environment supports.

pip resolves dependencies, downloads wheels or source distributions, builds them if necessary, and places the results on sys.path. For reproducible, fast installs on modern projects, see uv or poetry.

Install / upgrade pip#

pip is included with Python 3.4+. To ensure you have the latest version:

# Upgrade pip inside a virtual environment (recommended)
python -m pip install --upgrade pip

# Or use the ensurepip bootstrapper (useful when pip is missing)
python -m ensurepip --upgrade

Output:

Requirement already satisfied: pip in ./.venv/lib/python3.12/site-packages (24.0)
Collecting pip
  Using cached pip-24.1-py3-none-any.whl (1.8 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 24.0
    Uninstalling pip-24.0:
      Successfully uninstalled pip-24.0
Successfully installed pip-24.1

[!WARNING] Always upgrade pip inside an activated virtual environment. Running sudo pip install or upgrading the system pip can break OS-level Python tooling on Linux and macOS.

Install packages#

Single package#

pip install requests

Output:

Collecting requests
  Downloading requests-2.32.3-py3-none-any.whl (64 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 64.9/64.9 kB 3.2 MB/s eta 0:00:00
Collecting charset-normalizer<4,>=2
  Downloading charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.whl (140 kB)
Collecting idna<4,>=2.5
  Downloading idna-3.7-py3-none-any.whl (66 kB)
Collecting certifi>=2017.4.17
  Downloading certifi-2024.2.2-py3-none-any.whl (163 kB)
Collecting urllib3<3,>=1.21.1
  Downloading urllib3-2.2.1-py3-none-any.whl (121 kB)
Installing collected packages: certifi, idna, charset-normalizer, urllib3, requests
Successfully installed certifi-2024.2.2 charset-normalizer-3.3.2 idna-3.7 requests-2.32.3 urllib3-2.2.1

Multiple packages#

pip install requests pandas numpy

Output: (none — exits 0 on success)

From a requirements file#

pip install -r requirements.txt

Output: (none — exits 0 on success)

Extras#

Some packages expose optional dependency groups called extras:

pip install "uvicorn[standard]"
pip install "fastapi[all]"
pip install "requests[security,socks]"

Output: (none — exits 0 on success)

Editable install (development mode)#

An editable install links the package source directory directly into the environment so changes take effect without reinstalling:

pip install -e .
pip install -e ./path/to/my-package

Output:

Obtaining file:///home/user/myproject
  Installing build dependencies ... done
  Checking if build backend supports build_editable ... done
  Getting requirements to build editable ... done
  Installing backend dependencies ... done
  Preparing editable metadata (pyproject.toml) ... done
Building wheels for collected packages: myproject
  Building editable for myproject (pyproject.toml) ... done
  Created wheel for myproject: filename=myproject-0.1.0-py3-none-any.whl
Successfully installed myproject-0.1.0

User install (no virtual environment)#

pip install --user requests

Output: (none — exits 0 on success)

This installs to ~/.local/lib/pythonX.Y/site-packages instead of the system directory. Prefer using a virtual environment instead.

Version specifiers#

pip install "requests==2.32.3"    # exact version
pip install "requests>=2.28"      # at least
pip install "requests~=2.28"      # compatible release (>=2.28, <3)
pip install "requests!=2.30.0"    # exclude a broken release
pip install "requests>=2.28,<3"   # range

Output: (none — exits 0 on success)

Uninstall#

pip uninstall requests
pip uninstall requests pandas numpy   # multiple at once
pip uninstall -r requirements.txt     # everything listed in a file
pip uninstall -y requests             # skip confirmation prompt

Output:

Found existing installation: requests 2.32.3
Uninstalling requests-2.32.3:
  Would remove:
    /home/user/.venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/*
    /home/user/.venv/lib/python3.12/site-packages/requests/*
Proceed (Y/n)? Y
  Successfully uninstalled requests-2.32.3

[!WARNING] pip uninstall removes only the named package, not its dependencies. Use pip-autoremove (a separate package) if you need orphan dependency removal.

List installed packages#

pip list

Output:

Package            Version
------------------ ---------
certifi            2024.2.2
charset-normalizer 3.3.2
idna               3.7
pip                24.1
requests           2.32.3
setuptools         70.0.0
urllib3            2.2.1
pip list --outdated

Output:

Package    Version Latest Type
---------- ------- ------ -----
requests   2.28.0  2.32.3 wheel
urllib3    1.26.18 2.2.1  wheel
pip list --format=json        # machine-readable output
pip list --not-required       # packages not depended on by anything else

Output: (none — exits 0 on success)

Show package info#

pip show requests

Output:

Name: requests
Version: 2.32.3
Summary: Python HTTP for Humans.
Home-page: https://requests.readthedocs.io
Author: Alice Dev
Author-email: alice@example.com
License: Apache 2.0
Location: /home/user/.venv/lib/python3.12/site-packages
Requires: certifi, charset-normalizer, idna, urllib3
Required-by: httpx
pip show --verbose requests   # includes classifiers and more metadata
pip show requests urllib3     # show multiple packages at once

Output: (none — exits 0 on success)

Freeze / requirements.txt#

pip freeze writes the exact installed versions to stdout, suitable for pinning a working environment:

pip freeze > requirements.txt

Output (requirements.txt):

certifi==2024.2.2
charset-normalizer==3.3.2
idna==3.7
requests==2.32.3
urllib3==2.2.1

Restore that exact environment elsewhere:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Output: (none — exits 0 on success)

[!TIP] pip freeze includes every package, even transitive dependencies. For a curated requirements file that only lists your direct dependencies, use pip-tools (pip-compile) or uv pip compile. See Reproducible builds below.

Check for conflicts#

pip check

Output (no problems):

No broken requirements found.

Output (conflict detected):

sphinx 7.1.2 has requirement docutils<0.21,>=0.18.1, but you have docutils 0.21.

Run pip check in CI after installing dependencies to catch version conflicts that pip’s resolver sometimes misses with older lockfile approaches.

requirements.txt vs constraints.txt#

FilePurposeCommand
requirements.txtLists packages to install (with optional version pins)pip install -r requirements.txt
constraints.txtLimits versions of any package, including transitive deps, without installing thempip install -c constraints.txt -r requirements.txt

A constraints file lets you say “if anything installs urllib3, it must be <2” without adding urllib3 as an explicit dependency:

# constraints.txt
urllib3<2
certifi>=2023.1
pip install -c constraints.txt -r requirements.txt

Output: (none — exits 0 on success)

Index URLs and private registries#

Change the package index#

# Use a different index entirely
pip install requests --index-url https://pypi.mycompany.com/simple/

# Add a secondary index (PyPI is still tried first)
pip install requests --extra-index-url https://pypi.mycompany.com/simple/

Output: (none — exits 0 on success)

Persistent configuration#

Linux / macOS~/.pip/pip.conf or ~/.config/pip/pip.conf:

[global]
index-url = https://pypi.mycompany.com/simple/
extra-index-url = https://pypi.org/simple/
trusted-host = pypi.mycompany.com

Windows%APPDATA%\pip\pip.ini:

[global]
index-url = https://pypi.mycompany.com/simple/
trusted-host = pypi.mycompany.com

Per-projectpip.conf in the project root (add to .gitignore if it contains credentials):

pip config set global.index-url https://pypi.mycompany.com/simple/
pip config list   # show current effective config

Output: (none — exits 0 on success)

[!WARNING] Never hardcode credentials in pip.conf. Use the NETRC file (~/.netrc) or environment variables (PIP_INDEX_URL, PIP_EXTRA_INDEX_URL) injected from a secrets manager in CI.

Cache#

pip caches downloaded wheels to avoid re-downloading on future installs.

pip cache dir          # show the cache directory path
pip cache list         # list cached wheels
pip cache info         # summary of cache size and location
pip cache purge        # delete all cached files
pip cache remove requests   # remove cache entries for a specific package

Output:

$ pip cache dir
/home/user/.cache/pip

$ pip cache info
Location: /home/user/.cache/pip
Size: 1.2 GB
Number of packages: 347

$ pip cache purge
Files removed: 347

Disable the cache entirely (useful in Docker layers where caching wastes image space):

pip install --no-cache-dir -r requirements.txt

Output: (none — exits 0 on success)

Reproducible builds#

Hash-checking mode#

Generate hashes for your pinned requirements:

pip hash dist/requests-2.32.3-py3-none-any.whl

Output:

requests-2.32.3-py3-none-any.whl:
--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfed9b0832567fce85db745

In a requirements file, add the hashes:

requests==2.32.3 \
    --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfed9b0832567fce85db745 \
    --hash=sha256:58cd2187423d1a4600d4ae17b3ab5db0c7cf88ae81dbe6c3e7b5d65813b52d0c

Install with hash verification:

pip install --require-hashes -r requirements.txt

Output: (none — exits 0 on success)

pip-compile (pip-tools)#

pip-compile takes a high-level requirements.in and produces a fully pinned requirements.txt with hashes:

pip install pip-tools

# requirements.in
requests>=2.28
fastapi[all]

Output: (none — exits 0 on success)

pip-compile --generate-hashes requirements.in

Output:

#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
#    pip-compile --generate-hashes requirements.in
#
certifi==2024.2.2 \
    --hash=sha256:ab06db6... \
    ...
requests==2.32.3 \
    --hash=sha256:70761cf... \
    ...

Offline installs#

Download wheels for later#

# Download a package and all its dependencies into a local directory
pip download requests -d ./wheels

# Download for a specific platform (e.g., build on Linux, deploy on Linux)
pip download requests --platform manylinux2014_x86_64 --only-binary=:all: -d ./wheels

Output:

Collecting requests
  Downloading requests-2.32.3-py3-none-any.whl (64 kB)
Collecting certifi>=2017.4.17
  Downloading certifi-2024.2.2-py3-none-any.whl (163 kB)
...
Saved ./wheels/requests-2.32.3-py3-none-any.whl
Saved ./wheels/certifi-2024.2.2-py3-none-any.whl
Saved ./wheels/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.whl
Saved ./wheels/idna-3.7-py3-none-any.whl
Saved ./wheels/urllib3-2.2.1-py3-none-any.whl

Install from the local directory (no network)#

pip install --no-index --find-links ./wheels requests
pip install --no-index --find-links ./wheels -r requirements.txt

Output:

Looking in links: ./wheels
Collecting requests
  File was already downloaded /home/user/wheels/requests-2.32.3-py3-none-any.whl
Installing collected packages: certifi, idna, charset-normalizer, urllib3, requests
Successfully installed certifi-2024.2.2 charset-normalizer-3.3.2 idna-3.7 requests-2.32.3 urllib3-2.2.1

This pattern is common in air-gapped environments, Docker multi-stage builds, and corporate networks that block PyPI.

Comparison: pip vs uv vs poetry#

Featurepipuvpoetry
Ships with Python❌ (separate install)❌ (separate install)
Install speedSlowFast (Rust, 10–100×)Slow
Dependency resolverBasicFull SAT solverFull SAT solver
Lockfile❌ (use pip-tools)✅ (uv.lock)✅ (poetry.lock)
Virtual env management❌ (use venv)
Python version management
pyproject.toml supportPartial
Private registry support
Hash-checking mode
Offline installsPartial
Drop-in CLI compatibility✅ (uv pip …)

When to use pip: legacy projects, environments where you can’t install extra tools, scripting contexts where you need zero dependencies.

When to use uv: new projects, CI pipelines where speed matters, anywhere you’d use pip + pip-tools + virtualenv together.

When to use poetry: projects that prefer a pyproject.toml-first workflow and want a single tool for building, publishing, and dependency management.

Common errors#

ErrorCauseFix
ERROR: Could not find a version that satisfies the requirement <pkg>Package name typo, wrong index, or no wheel for your Python/platformCheck the name on PyPI; add --extra-index-url; try --pre for pre-releases
ERROR: pip's dependency resolver does not currently take into account all the packages that are installedConflict between existing packages and the new installCreate a fresh virtual environment; use uv for better resolution
Permission denied when installingInstalling into system Python without sudo, or inside a read-only venvActivate your virtual environment first; never use sudo pip
No module named pippip was removed or never installedRun python -m ensurepip --upgrade
SSL: CERTIFICATE_VERIFY_FAILEDMissing or outdated CA certificatesUpgrade certifi; use --trusted-host for private registries with self-signed certs
ERROR: Failed building wheel for <pkg>Missing C compiler or system headers needed to build a source distributionInstall build tools (build-essential on Debian/Ubuntu, Xcode CLT on macOS); prefer wheels with --only-binary=:all:
WARNING: The scripts <cmd> are installed in '~/.local/bin' which is not on PATH--user install destination not on PATHAdd ~/.local/bin to your PATH in ~/.bashrc or ~/.zshrc
pkg_resources.DistributionNotFoundPackage installed in a different environment than the one running PythonConfirm the correct venv is active; run pip show <pkg> to check location