On modern macOS, almost every "broken Python" problem is really a path or interpreter mismatch: pip installs a package against one Python interpreter while your terminal runs a different one, so import fails even though the install succeeded. The reliable fix is to stop touching system paths and instead run everything through a per-project virtual environment, where python, python3, pip, and pip3 all resolve to the same isolated interpreter. Apple removed bundled Python 2 in macOS 12.3 (2022), Homebrew now installs to /opt/homebrew on Apple Silicon, and pip refuses to write into the system environment by default (PEP 668) — so guides that predate those changes will send you down the wrong path.
That's the summary an AI Overview would give you. Here's what it can't show you: the actual decision flow for figuring out which Python you're running, a symptom-to-cause-to-fix lookup for the specific errors you'll hit, and a copy-paste recovery checklist. Start with the diagnosis diagram, then jump to whichever row matches your error.
Diagnose it first: which Python is actually running?
Before you change anything, find out which interpreter your shell picks and whether pip is tied to it. Run these four commands — the answers tell you exactly where the mismatch is:
which python3 # which interpreter the shell resolves
python3 -m pip --version # which pip, and which interpreter it belongs to
brew --prefix # /opt/homebrew (Apple Silicon) or /usr/local (Intel)
echo $PATH # the search order that decides all of the above
The single most useful command here is python3 -m pip. It forces pip to run as a module of the interpreter you just invoked, which guarantees the install and the import use the same Python. If python3 -m pip install requests works but plain pip install requests doesn't, you've found your bug: bare pip points somewhere else.
Symptom to cause to fix
Match your exact error to a row. These are the failures you actually hit on macOS Ventura, Sonoma, and Sequoia — not the pre-2022 world of system Python 2.
| Symptom | Root cause | Fix |
|---|---|---|
pip: command not found (but python3 works) | Homebrew installs pip3, not bare pip; bare pip only exists inside a venv | Use pip3 or python3 -m pip, or activate a virtualenv |
error: externally-managed-environment | PEP 668 blocks pip from writing into Homebrew's Python | Create a venv, or use pipx for CLI tools; avoid --break-system-packages |
Install succeeds, import says ModuleNotFoundError | pip and python point at different interpreters | Run python3 -m pip install … so both share one interpreter |
which python3 → /usr/bin/python3 not Homebrew | /usr/bin sits ahead of Homebrew in PATH | Add eval "$(/opt/homebrew/bin/brew shellenv)" to ~/.zprofile, reopen terminal |
python: command not found | No bare python on modern macOS by design | Activate a venv (gives you python), or install python via pyenv |
command not found after pip install some-cli | The tool's script dir isn't on PATH | Prefer pipx install some-cli, which puts binaries on PATH automatically |
| Permission denied writing packages | You previously ran sudo pip and left root-owned files | sudo chown -R $(whoami) the affected dir, then never sudo pip again |
Wrong version after brew upgrade | An old venv still references the deleted interpreter | Delete and recreate the venv: rm -rf .venv && python3 -m venv .venv |
Which fix should you reach for?
There isn't one "install Python" answer anymore. Pick the tool that matches the job:
| Tool | Best for | When to use it |
|---|---|---|
Homebrew python@3.x | A single system-wide Python 3 interpreter | You just need a recent Python to build venvs from |
| venv (built-in) | Per-project dependency isolation | Every project — this is the default answer for "fix my Python" |
| pipx | Standalone CLI tools (black, poetry, httpie) | Installing command-line apps without polluting any project |
| pyenv | Multiple Python versions side by side | You need 3.10 and 3.12, or a specific legacy version |
| conda / miniforge | Scientific stacks with compiled deps | Data/ML work where NumPy/SciPy wheels fight the toolchain |
If you only remember one rule: use venv for projects and pipx for tools, and let Homebrew supply the base interpreter. That combination eliminates the vast majority of macOS path conflicts before they start.
Preventing Python problems
Most issues come down to a mismatch between where Python is installed, what paths are on your PATH, and where pip drops your packages. When those three disagree, you install a package with pip and Python still insists it's missing. Virtual environments fix this permanently by giving each project its own interpreter and its own package directory, so there's nothing to misalign.
Key rule: Never use sudo to install Python packages. sudo pip install writes files as root into a directory your normal user can't manage, and modern pip blocks it anyway. Install into a venv or with pipx, both of which live in your own user space.
Set up a virtual environment (the 30-second version)
cd ~/my-project
python3 -m venv .venv # create an isolated environment
source .venv/bin/activate # activate it — prompt now shows (.venv)
pip install requests # installs into .venv only; bare pip now works
python app.py # runs against the venv's interpreter
deactivate # leave the environment when done
Inside an activated venv, python, python3, pip, and pip3 all resolve to the same place. That's the entire fix for "pip installed it but Python can't find it."
Recovery checklist
Work top to bottom. Each step is safe and non-destructive until the reinstall at the end.
Checking system and Python paths
Your PATH tells the shell which directories to search, in order, when you type a command. If Homebrew's bin directory appears after /usr/bin, you'll get Apple's stub Python instead of the one you installed.
Check your PATH and interpreter
echo $PATH
which python3
which pip3
You want to see your Homebrew bin directory (/opt/homebrew/bin on Apple Silicon, /usr/local/bin on Intel) listed before /usr/bin. If it isn't, add Homebrew to your shell startup and reopen the terminal:
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
Inspect where a given Python looks for packages
python3 -c "import sys; print(sys.path)"
python3 -m site # shows the site-packages directory in use
Comparing sys.path between two interpreters is the fastest way to prove that an install landed in a directory a different Python never searches.
Understanding where Python lives on macOS
Knowing the layout makes path problems obvious rather than mysterious.
- Apple's stub:
/usr/bin/python3— triggers the Xcode Command Line Tools; fine for quick scripts, not for managing packages. - Homebrew (Apple Silicon): interpreter under
/opt/homebrew/Cellar/python@3.x/…, symlinked to/opt/homebrew/bin/python3. - Homebrew (Intel): the same, but rooted at
/usr/localinstead of/opt/homebrew. - Virtual environment:
./.venv/bin/pythonand./.venv/lib/python3.x/site-packages— self-contained and per-project.
There is no bundled Python 2 on macOS 12.3 or later. If a legacy project truly needs it, install Python 2 through pyenv in isolation rather than expecting the OS to provide it.
Reinstalling Python (last resort)
If diagnostics point at a genuinely corrupted interpreter — not just a path mismatch — reinstall through Homebrew:
brew uninstall python@3.12 # match your installed version
brew cleanup
brew install python@3.12
brew link python@3.12
Reinstalling replaces only the interpreter. Your virtual environments hold their own package copies, so any venv built against the old interpreter should be deleted and recreated afterward. Resist the urge to hand-edit .pth files in site-packages or to modify /etc/paths — those changes drift out of sync with Homebrew and reintroduce exactly the mismatches this guide exists to prevent.