Apollo's Blog

Fixing pyenv version system not installed

If you're using pyenv to manage Python versions, you might encounter a frustrating issue where the system version doesn't seem to work as expected. For instance, even when pyenv shell system is set, running python results in an error like this:

$ python --version
pyenv: python: command not found

In this post, I’ll walk you through the steps to understand and resolve this issue. By the end, you’ll have a working pyenv configuration that properly recognizes the system Python.

The Problem

Here’s an example of the issue in action:

#
# Check available pyenv install version:
#
$ pyenv versions
  system
  2.7.18
* 3.12.8 (set by PYENV_VERSION environment variable)

#
# Switch shell's python to pyenv system: 
#
$ pyenv shell system
$ pyenv versions
* system (set by PYENV_VERSION environment variable)
  2.7.18
  3.12.8

#
# Confirm python version
#
$ python --version
pyenv: python: command not found

The `python` command exists in these Python versions:
  2.7.18
  3.12.8

Note: See 'pyenv help global' for tips on allowing both
      python2 and python3 to be found.

After some investigation, I found Issue #1301 on the pyenv GitHub repository, which discusses this exact problem. However, that issue was closed and marked as fixed in May 2021. Fast forward to December 2024, and I’m still facing this issue using:

$ pyenv --version
pyenv 2.5.0

What the Documentation Says

The documentation explains the behavior of pyenv system as follows:

A special version name "system" means to use whatever Python is found on PATH after the shims PATH entry (in other words, whatever would be run if Pyenv shims weren't on PATH). Note that Pyenv considers those installations outside its control and does not attempt to inspect or distinguish them in any way. So e.g. if you are on macOS and have OS-bundled Python 3.8.9 and Homebrew-installed Python 3.9.12 and 3.10.2 — for Pyenv, this is still a single "system" version, and whichever of those is first on PATH under the executable name you specified will be run.

To investigate available python commands in my PATH, I temporarily deactivated Homebrew and pyenv by commenting out the related lines in my .bashrc:

# =============
# PATH
# =============
#eval "$(/opt/homebrew/bin/brew shellenv)" # Homebrew PATH and environment
...
...
# =============
# PYENV
# =============
#export PYENV_ROOT="$HOME/.pyenv"
#[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
#eval "$(pyenv init -)"

With pyenv and Homebrew deactivated, the system should fall back to the default Python available on macOS. However, the following command:

which python

returns nothing, meaning the python command is not present in my PATH:

$ echo "$PATH" | sed $'s/:/\\\n/g'
/Users/apollotang/.local/bin
/Users/apollotang/_x_conf/bin
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
/Applications/iTerm.app/Contents/Resources/utilities

The Default Python on macOS

What is the default "system" Python that comes with macOS? According to the macOS Monterey 12.3 Release Notes:

Python 2.7 was removed from macOS in this update. Developers should use Python 3 or an alternative language instead. (39795874)

This suggests that the available default Python command should be python3:

$ which python3
/usr/bin/python3

An intuitive solution is to create a symlink from /usr/bin/python to /usr/bin/python3. However, doing so triggers the macOS developer tools installation prompt. For more details, see this post.

Using Homebrew’s Python

If I can’t symlink /usr/bin/python to /usr/bin/python3, I can use the Python installed via Homebrew. To do this, I reactivated Homebrew:

eval "$(/opt/homebrew/bin/brew shellenv)" # Homebrew PATH and environment

Adding Homebrew to my PATH yields:

$ echo "$PATH" | sed $'s/:/\\\n/g'
....
/opt/homebrew/bin
/opt/homebrew/sbin
....

Investigating the Python installation by Homebrew reveals:

$ brew info python
==> python@3.13: stable 3.13.1 (bottled)
....
Installed
/opt/homebrew/Cellar/python@3.13/3.13.1 (3,299 files, 65.6MB) *
....
Python is installed as
  /opt/homebrew/bin/python3

Unversioned symlinks `python`, `python-config`, `pip` etc., pointing to
`python3`, `python3-config`, `pip3` etc., respectively, are installed into
  /opt/homebrew/opt/python@3.13/libexec/bin

The response of brew info python tell us that the python command is installed at:

$ /opt/homebrew/opt/python@3.13/libexec/bin/python --version
Python 3.13.1

Since this location is not in my PATH, I created a symlink for this python command in homebrew/bin:

$ ln -s /opt/homebrew/opt/python@3.13/libexec/bin/python /opt/homebrew/bin/python
$ python --version
Python 3.13.1

Reactivating pyenv

Finally, I reactivated pyenv:

# =============
# PYENV
# =============
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

Verifying the setup:

$ pyenv versions
* system (set by /Users/apollotang/.pyenv/version)
  2.7.18
  3.12.8

$ python --version
Python 3.13.1

$ which python
/Users/apollotang/.pyenv/shims/python

With this configuration, pyenv now correctly recognizes the system Python.

#pyenv