Previously I have written
about what I tried and what did and did not work while trying to satisfy
neovim's :checkhealth
command while detecting the Python provider on Mac
M3.
Yeah, the solution worked but it was less than optimal, due to the use of
--break-system-packages
option, which should not be used. It is designed
to sound scary in the first place. While I did not encounter any situations
that would I classify as broken system packages I have since found a
better, hopefully a proper way to install pynvim
in a way that would
satisfy neovim.
Introduction
At the beginning there was this message. It happens when Python is installed via Homebrew. It is very hard to use brew without it, as most really useful packages, at least the ones that I use, depend on Python.
However, trying to install something via homebrew's like so:
pip3 instal some_random_package
Leads to the following error:
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try brew install
xyz, where xyz is the package you are trying to
install.
If you wish to install a Python library that isn't in Homebrew,
use a virtual environment:
python3 -m venv path/to/venv
source path/to/venv/bin/activate
python3 -m pip install xyz
If you wish to install a Python application that isn't in Homebrew,
it may be easiest to use 'pipx install xyz', which will manage a
virtual environment for you. You can install pipx with
brew install pipx
You may restore the old behavior of pip by passing
the '--break-system-packages' flag to pip, or by adding
'break-system-packages = true' to your pip.conf file. The latter
will permanently disable this error.
If you disable this error, we STRONGLY recommend that you additionally
pass the '--user' flag to pip, or set 'user = true' in your pip.conf
file. Failure to do this can result in a broken Homebrew installation.
Read more about this behavior here: <https://peps.python.org/pep-0668/>
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
I am sure I have read the log error message from above carefully back then,
and that I even tried to use the venv, but I am sure I failed. Not
remembering why. Anyway, for the record, making sure pip3
in this case is
really the one installed via Homebrew:
which pip3 # /opt/homebrew/bin/pip3
But there is another pip3
on the system...
System wide Python
Note that it is possible to completely overcome the above error message by
running the system-wide pip3
:
/usr/bin/pip3 install some_random_package
# Defaulting to user installation because normal site-packages is not writeable
The above works but it is discouraged for at least two reasons:
- The Python there is older, 3.9 versus 3.13 at the time of writing
- It is better to leave system space as intact as possible
Moreover, since system space actually is not writable, the installation
will store the files into user space under ~/Library/Python/3.9/
, making
it even harder to manage. So what is the proper way?
Reverting the damage
Before installing pynvim
properly, first address the possible damage.
Check if there are system-wide Python packages installed at all, hopefully
not:
/usr/bin/pip3 list
If there are any, consider completely removing them too:
Warning: The following command might cause damage to your system, inspect carefully before use.
/usr/bin/pip3 uninstall -y (/usr/bin/pip3 list | tail -n +3 | string split -f1 ' ')
Packages removed this way should be replaced, as the long error above
suggests, either via Homebrew's pipx
or via Python virtual environment,
which we are going to discuss here in this post.
Next, more certain step is to remove pynvim
from Homebrew as we installed
it incorrectly and we want to stop using this installation:
pip3 uninstall pynvim `--break-system-packages`
Note that that the --break-system-packages
switch is again required here,
even for removal, hopefully your system has no Homebrew packages depending
on it, which is unlikely.
Using venv
Now read the long error message from the beginning. It actually writes the guidelines what to do to use the virtual environment, but not in an exact way an also missing the critical points. Here's a compacted list of commands that worked for me:
mkdir -p ~/.config/nvim/venv
/opt/homebrew/bin/python3 -m venv ~/.config/nvim/venv
source ~/.config/nvim/venv/bin/activate
pip install pynvim
# Leave virtual environment
deactivate
Note that when using fish
shell, activation will fail with the error:
~/.config/nvim/venv/bin/activate (line 40): 'case' builtin not inside of switch block
case "$(uname)" in
^~~^
from sourcing file ~/.config/nvim/venv/bin/activate
source: Error while reading file '/Users/peterbabic/.config/nvim/venv/bin/activate'
In that case use the specialized activation script:
source ~/.config/nvim/venv/bin/activate.fish
Also note that the location for the environment is conveniently placed
inside ~/.config/nvim/
where my other neovim related files reside,
resulting in a neat and clean setup.
Configuring nvim
Last important thing to do is to locate and replace the python3_host_prog
parameter from Homebrew to the venv like the your .vimrc
or init.vim
file:
let g:python3_host_prog = expand('~/.config/nvim/venv/bin/python')
Now run :checkhealth
in neovim again. It should now not complain about
missing Python provider. Here's how it could possibly look:
provider.python: require("provider.python.health").check()
Python 3 provider (optional) ~
- Using: g:python3_host_prog = "/Users/peterbabic/.config/nvim/venv/bin/python"
- Executable: /Users/peterbabic/.config/nvim/venv/bin/python
- Python version: 3.13.2
- pynvim version: 0.5.2
- OK Latest pynvim is installed.
Python virtualenv ~
- OK no $VIRTUAL_ENV
Enjoy!