pip is the most-used and most-misused tool in this quest. These rules separate Python developers whose environments work from those who fight their environments daily.
Always use virtual environments. Never sudo pip. Globally installing packages mixes them with system Python's libs and breaks both. Every Python project deserves its own venv.
Use python3 -m venv, not virtualenv. The stdlib venv module is built in and good enough. The third-party virtualenv package adds features most users don't need and is a relic of the Python 2 era.
Use pip-tools if you need real reproducibility on pip. pip-compile turns a small requirements.in into a fully-pinned requirements.txt. It's the right answer for projects that want strict reproducibility but can't switch to uv yet.
Consider uv for new Python projects. uv is 10-100x faster, has a real lockfile, manages Python versions, and replaces pip + venv + pip-tools + pyenv + pipx in one binary. The next track is dedicated to it.
Mind macOS PEP 668. Newer macOS Pythons restrict global pip installs to prevent breaking system tools. The error is 'externally-managed-environment'. The right fix is to use a venv. The wrong fix is --break-system-packages.