I use pyenv (installed with homebrew) to manage my macOS python-versions.
Python 3.11 just came out, but pyenv doesn't see this version. However from googling it appears others are able to see/install it.
How to fix?
This caused me some trouble, so I'm gona jot my solution down in case it's useful (and in case others can improve upon the solution path).
EDIT: On a fresh macOS, I bumped into: UserWarning: Could not import the lzma module. Your installed Python is incomplete and (as per answers there) did brew install xz before pyenv install 3.11.0.
The first issue was that the homebrew-installed pyenv doesn't see the new 3.11. So I had to uninstall it and re-install using pyenv's recommended method:
> brew uninstall pyenv
> # rm -rf ~/.pyenv
> curl https://pyenv.run | bash
> pyenv install 3.11.0
> pyenv global 3.11.0
> which python ; python --version # sanity check
(Note: You'll lose your current .pyenv-s if you rm -rf ~/.pyenv -- I did it to keep things simple but don't know if it's needed)
Now to test it out:
> python -m venv --upgrade-deps .venv
> which python ; which pip
So far so good, but if I create a foo.py that does import requests, and:
> pip install requests
> python foo.py
... I get "ModuleNotFoundError: No module named 'requests'"
Which is confusing.
An engineer suggested I inspect python -m site but I lost the original output.
Next I see at the bottom of my ~/.bash_profile:
# recommendation by homebrew from `brew install pyenv`
if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi
export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
Now I'm pretty sure the last time I installed pyenv (using homebrew) it suggested this, so I copy+pasted it into my ~/.bash_profile.
But it turns out I needed an additional:
eval "$(pyenv init --path)"
Now I restart my terminal and boom it works.
> pyenv init --path
PATH="$(bash --norc -ec 'IFS=:; paths=($PATH); for i in ${!paths[#]}; do if [[ ${paths[i]} == "'/Users/pi/.pyenv/shims'" ]]; then unset '\''paths[i]'\''; fi; done; echo "${paths[*]}"')"
export PATH="/Users/pi/.pyenv/shims:${PATH}"
command pyenv rehash 2>/dev/null
This appears to be removing any pyenv shims from the PATH env-var and prepending the correct shim to the PATH.
Now what about the original pyenv init - command? What does that do?
> pyenv init -
PATH="$(bash --norc -ec 'IFS=:; paths=($PATH); for i in ${!paths[#]}; do if [[ ${paths[i]} == "'/Users/pi/.pyenv/shims'" ]]; then unset '\''paths[i]'\''; fi; done; echo "${paths[*]}"')"
export PATH="/Users/pi/.pyenv/shims:${PATH}"
export PYENV_SHELL=bash
source '/Users/pi/.pyenv/libexec/../completions/pyenv.bash'
command pyenv rehash 2>/dev/null
pyenv() {
local command
command="${1:-}"
if [ "$#" -gt 0 ]; then
shift
fi
case "$command" in
activate|deactivate|rehash|shell)
eval "$(pyenv "sh-$command" "$#")"
;;
*)
command pyenv "$command" "$#"
;;
esac
}
This all seems confusing. The above is documented in https://github.com/pyenv/pyenv#advanced-configuration but do I really need such a complex path to achieve something that feels like it should be 'out-of-the-box'?
I have pyenv installed and have downloaded python versions 3.6.15 and 3.7.12. When I run
pyenv global 3.7.12
python -V
the output is: Python 3.10.2
pyenv versions gives the output
system
3.6.15
* 3.7.12 (set by /home/frege/.pyenv/version)
$ echo $PYENV_ROOT: /home/frege/.pyenv
$ which python: /user/bin/python
$ type python: python is hashed (/usr/bin/python)
I have the following in my .bashrc
export PATH="${HOME}/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
I have restarted my terminal and $PATH contains
/home/frege/.pyenv/plugins/pyenv-virtualenv/shims:
/home/frege/.pyenv/bin:
...
/usr/bin:
What is wrong?
I understand that getting pyenv and virtualenvs to work together can be problematic. I came from virtualenvwrapper which makes working on virtual envs simple and I found pyenv a bit of a culture shock.
I have finally got my workflow sorted and I thought I would post it here as it might help someone. My OS is Manjaro.
I installed pyenv:
curl https://pyenv.run | bash
The following was added to .bashrc:
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/shims:${PATH}"
export PATH="$PYENV_ROOT/bin:$PATH"
export PYENV_VIRTUALENVWRAPPER_PREFER_PYVENV="true"
export WORKON_HOME=$HOME/.virtualenvs
eval "$(pyenv init -)"
pyenv virtualenvwrapper_lazy
(I have not seen the line export PATH="$PYENV_ROOT/shims:${PATH}" in many explanations, but it is critical in mine.)
To invoke a global version of python:
pyenv shell <version>
or
pyenv shell system
To create a virtual env:
pyenv virtualenv <version> <env name>
To activate the virtual environment:
pyenv activate <env name>
To deactivate the virtual environment:
source deactivate
I've got some problems with activating virtual environments using pyenv-virtualenv. When I activate an environment with pyenv, it looks like it worked. However the python version has not changed. The only way to activate it is to manually run the activation script in the corresponding folder:
/usr/bin/python
➜ ~ pyenv activate test_env
pyenv-virtualenv: prompt changing will be removed from future release. configure `export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
(test_env) ➜ ~ which python
/usr/bin/python
(test_env) ➜ ~ source .pyenv/versions/test_env/bin/activate
(test_env) ➜ ~ which python
/Users/tom/.pyenv/versions/3.9.6/envs/test_env/bin/python
(test_env) ➜ ~
I added these two lines to my .zshrc:
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
I'm using zsh with Oh My Zsh on macOS 11.6 on an M1 MacBook Pro.
If you're using Pyenv 2.0+, also add eval "$(pyenv init --path)" to .zprofile and make sure your Terminal runs Zsh as a login shell.
(See installation instructions for Zsh in MacOS in https://github.com/pyenv/pyenv#readme)
Goal: Use ESPHome Flasher https://github.com/esphome/esphome-flasher
TLDR: Starting esphomeflasher I get this error message:
This program needs access to the screen. Please run with a
Framework build of python, and only when you are logged in
on the main display of your Mac.
Python Setup: https://opensource.com/article/19/5/python-3-default-mac
Mac Setup: Fresh Catalina installation.
Steps:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install pyenv
pyenv install 3.9.1
pyenv global 3.9.1
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.zshrc
pip install --upgrade pip
Install esphomeflasher: https://github.com/esphome/esphome-flasher
Steps:
pip3 install wxpython
pip3 install esphomeflasher
Problem:
Starting esphomeflasher I get the following error:
This program needs access to the screen. Please run with a
Framework build of python, and only when you are logged in
on the main display of your Mac.
I found this but don't know how to apply it in my case.
https://blurringexistence.net/wxpython-using-virtualenvwrapper-on-osx.html
My .zshrc config:
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
PATH=$(pyenv root)/shims:$PATH
# We want to regularly go to our virtual environment directory
echo 'export WORKON_HOME=~/.virtualenvs' >> .zshrc
# If in a given virtual environment, make a virtual environment directory
# If one does not already exist
echo 'mkdir -p $WORKON_HOME' >> .zshrc
# Activate the new virtual environment by calling this script
# Note that $USER will substitute for your current user
echo '. ~/.pyenv/versions/3.9.1/bin/virtualenvwrapper.sh' >> .bash_profile
export WORKON_HOME=~/.virtualenvs
mkdir -p $WORKON_HOME
export WORKON_HOME=~/.virtualenvs
mkdir -p $WORKON_HOME
I am try to upgrade my Python version on my macOS Catalina 10.15.1 by install PYENV and PYPIP, and set global and local to version 3.8.0. but still when I try to python version it shows the python version which built into the MacOS operating system. which part is missing?
$ pyenv -v
pyenv 1.2.14
$ pypip -v
zsh: command not found: pypip
$ pyenv versions
system
* 3.8.0 (set by /Users/aj/.python-version)
$ pyenv global
3.8.0
$ pyenv local
3.8.0
$ python -V
Python 2.7.16
For me OSX I had to put
eval "$(pyenv init --path)"
inside my ~/.bashrc | ~/.zshrc
note that without the --path it didn't work
If the output of
type -a python
is /usr/bin/python, and if there is no second line displayed, then pyenv is only setup partially.
You should have seem as first line something like
/home/username/.pyenv/shims/python
That means your pyenv is not setup properly. It is only set up partially.
What's missing is the pyenv shims which redirect to the correct version of python.
Probably your search path contains:
/home/username/.pyenv/bin, but it is missing /home/username/.pyenv/shims
(Following comments updated 2021-01-06):
Normally you should have three lines in your ~/.bashrc
The first two (or something equivalent), that you seem to have are:
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
On the other hand what you seem to be missing is a line, that looks like:
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
or a more elaborate but in most cases identical line:
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bash_profile
Try to add one of these missing lines to your .bashrc and see whether pyenv is working better.
You could also add ~/.pyenv/shims/python manually to your searchpath, but normally this should have been done by the eval "$(pyenv init -)" command
if ~/.pyenv/shims is already in your search path, then check with
ls ~/.pyenv/shims
whether the directory exists and contains an executable named python.
Normally this should have been added latest after having done a pyenv install 3.8.0
Addendum 2022-01-15:
Please note that the way pyenv is initialized changed.
If you had an older pyenv version and you updated the cloned repository you have probably something like
eval "$(pyenv init -)"
in your ~/.bash_profile
This has to be changed to something lile
eval "$(pyenv init -)"
eval "$(pyenv init --path)"
In case you have multiple versions of python installed (you can use pyenv versions to see all the installed versions), you can set a particular one as local or global version:
$ pyenv versions
system
* 2.7.18
* 3.7.8
3.9.9
$ pyenv global 3.9.9
$ pyenv versions
system
2.7.18
3.7.8
* 3.9.9
As gelondia mentioned, you might need to add this code to your ~/.bash_profile to get your PATH setup correctly:
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
echo $PATH should return something like /Users/matthewpowers/.pyenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin. Notice that the ~/.pyenv/shims directory is out front.
I added a separate answer because I think you should add some different code to your ~/.bash_profile than what gelonida is suggesting.
This post used to contain valuable additional information that was removed by the mods for reasons I do not understand.
Recently, this only works on macOS:
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init --path)"
fi
Previously, I used pyenv init - only, which stopped doing its job at some point. But, if you want autocompletion just append both of them together, like this:
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
fi
You can try running pyenv-installer made by the same owners of pyenv. Running the script is as easy as
curl https://pyenv.run | bash