Soma Suzuki
Soma Suzuki

Reputation: 2661

Cannot switch Python with pyenv

I would like to use pyenv to switch python2 and python3. I successfully downloaded python2 and python3 and pyenv with following code.

brew install pyenv

brew install pyenv-virtualenv

pyenv install 2.7.10

pyenv install 3.5.0

However, I cannot switch from python2 to python3..

Soma-Suzuki:~ Soma$ python --version
Python 2.7.10
Soma-Suzuki:~ Soma$ pyenv global
2.7.10
Soma-Suzuki:~ Soma$ pyenv versions
  system
* 2.7.10 (set by /Users/Soma/.pyenv/version)
  3.5.0
Soma-Suzuki:~ Soma$ pyenv global 3.5.0
Soma-Suzuki:~ Soma$ pyenv global
3.5.0
Soma-Suzuki:~ Soma$ pyenv versions
  system
  2.7.10
* 3.5.0 (set by /Users/Soma/.pyenv/version)
Soma-Suzuki:~ Soma$ python --version
Python 2.7.10
Soma-Suzuki:~ Soma$ 

I do not understand why this happens.

My python is in this directory.

Soma-Suzuki:~ Soma$ which python
/usr/bin/python

Upvotes: 262

Views: 250233

Answers (30)

Tim
Tim

Reputation: 31

This is a constant issue for me and none of these answers have worked. I've found that when I check pyenv versions, it will say:

Python 3.9.6(version set by PYENV_VERSION environment variable)

I just unset that environment variable and that solves the issue.

export PYENV_VERSION=""

Upvotes: 2

Jaeyoon Jeong
Jaeyoon Jeong

Reputation: 709

In my case, I used the terminal embedded in vscode. After changing version of python with pyenv, vscode changed python environment to the previous version when I open a new terminal.If you're in my case, it might be helpful to check interpreter settings in vscode.

Upvotes: 2

azizbro
azizbro

Reputation: 4240

After running brew install pyenv it's good to reference the OG docs on setting up your shell environment from the pyenv github README:

https://github.com/pyenv/pyenv#set-up-your-shell-environment-for-pyenv

As of version 2.3.0 and zsh, the following should be run

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc

Upvotes: 6

Naman Khandelwal
Naman Khandelwal

Reputation: 128

For someone who gets this error in the future.

In my case it was related to an extra directory created inside ~/.pyenv/versions folder.

I was not able to change my python version to 3.10.11. And the reason was this extra directory which looked like: ~/.pyenv/versions/3.10.11\ /. Looking into the contents of this dir weren't useful so tried removing it and it worked.

Upvotes: 0

Wizard.Ritvik
Wizard.Ritvik

Reputation: 11612

The answers by @Powers and by @Boby actually helped steer me in the right direction, albeit in a roundabout way.

In my case, I tried everything, including: upgrading/installing pyenv with brew using brew upgrade pyenv, adding config for pyenv to my ~/.zshrc file, then removing it from there and adding it to ~/.zprofile, and basically everything in between.

The problem was that when I activated a particular Python version that I had installed, such as:

pyenv global 3.6.15

It didn't actually work. When I typed python in a terminal, it still showed my system Python version, which was different (3.11)

Long story short, I eventually happened upon the fix rather unintentionally, when I was in the midst of updating my ~/.zprofile based on another answer, and then opening up a new terminal window to test out whether that fixed or resolved the issue.

I noticed a peculiar strangeness, in that under my user home ~ directory, the Python version was 3.6 correctly (as set in pyenv) but when I cd-ed into the folder I was having trouble with, it gave me a different python version when I ran python.

So, thus confused and rendered rather speechless, I ran the following command on my terminal from within this folder:

$ ls -la

And lo and behold, what I did I get other than:

drwxr-xr-x  37 usr  staff   1184 Mar 23 17:14 .
drwxr-x---+ 94 usr  staff   3008 Mar 30 16:01 ..
-rw-r--r--@  1 usr  staff  16388 Mar 13 11:17 .DS_Store
-rw-r--r--   1 usr  staff      7 Feb 10 18:10 .python-version
-rw-r--r--@  1 usr  staff    170 Feb  9  ?     Other stuff

Aha! The culprit (in my case) was the .python-version file.

I cated it, and found the contents of the file was just plainly:

system

Cleaning up by deleting the file, by running:

rm .python-version

Resolved the issue in my case.

FYI, it looks like this is a trickle-down effect, so that if I had a .python-version file under:

~/git-repos

Then the same settings (overriding Python version for pyenv) applies to any children sub-folders, such as:

~/git-repos/my-repo

Solution, was to entirely remove any .python-version files, all the way up to (and potentially including) the user home or ~ directory on my Mac OS.

Hope this helps someone else, who ends up in the same boat or situation as me.

Upvotes: 1

Shady Smaoui
Shady Smaoui

Reputation: 1267

Do it manually. Change the path within your ~/.zprofile

vim ~/.zprofile
 PATH="/Users/you-user-name/.pyenv/versions/3.10.9/bin:${PATH}"
 export PATH

Upvotes: 0

KZiovas
KZiovas

Reputation: 4709

In ubuntu the ~/.bashrc file needs to be updated and change eval "$(pyenv init -)" to eval "$(pyenv init --path)".

Edit: Just to point out that the change will be in effect after restarting the terminal. If you do not want to restart the terminal you can also do an extra step in addition to changing the file. In the terminal execute the same command you changed in the file: eval "$(pyenv init --path)"

Upvotes: 93

ThomasAFink
ThomasAFink

Reputation: 1377

Run eval "$(pyenv init -)" (note the quotes) in the Terminal on Mac OS to add Pyenv shims directory to PATH. Then run pyenv global 3.5.0 again and check with python3 --version.

Upvotes: 11

ozgurcen
ozgurcen

Reputation: 21

I installed pyenv and pyenv-virtualenv with brew too and had the same issue.

It's easy to solve after you know exactly what to do:

1- You need to know what shell interpreter you are using. Direct quoting from the https://support.apple.com/en-us/HT208050

By default, your Mac uses either zsh or bash as the command-line interpreter for the login shell and interactive shell:

  • zsh (Z shell) is the default shell for all newly created user accounts, starting with macOS Catalina.
  • bash is the default shell in macOS Mojave and earlier.

And of course, each interpreter is using different files for environment variables, like PATH, JAVA_HOME etc.
bash is using $HOME/.bash_profile and $HOME/.bashrc, while zsh is using $HOME/.zprofile and $HOME/.zshrc

2- After installing pyenv and installing the python version which you want to use (e.g. pyenv install 3.y), open the /.bash_profile or /.zprofile file wrt your interpreter.

Note1: I'm using bash interpreter and my $HOME/.bashrc file is empty. So I don't know what happens whether any PATH declaration in the /.bashrc would affect the /.bash_profile declarations or not. You may need to check this.

3- pyenv creates $HOME/.pyenv/shims directory and uses this to switch python versions that you installed.

So you just need to add the following line to the bottom (not necessarily to the very bottom of the file. You just need to go to the end of all PATH declarations.)

export PATH=$HOME/.pyenv/shims:$PATH

Note2: "$HOME/.pyenv/shims" MUST be at the beginning of the PATH variable. Because all the paths are read from left to right order by the interpreter. So be careful adding new paths to the PATH variable in the future.

Note3: There are two commands that sets python version. One is "pyenv global #python_version_here#" and the other is "pyenv local #python_version_here#". Under a directory, hierarchically "local" command is top of "global" one. So, if you run the "local" command under $HOME directory, you cannot change the global python version with the "global" command. In that case, either
1- You can continue to use "local" command under the $HOME directory
2- Delete $HOME/.python-version file and return to "global" setting

This is my shell output to show this hierarchy:

Ozgurs-MacBook-Pro:~ ozgurcengelli$ pyenv global system  
Ozgurs-MacBook-Pro:~ ozgurcengelli$ pyenv versions  
* system (set by /Users/ozgurcengelli/.pyenv/version) #look the path  
  3.6.15  
Ozgurs-MacBook-Pro:~ ozgurcengelli$ pyenv local system  
Ozgurs-MacBook-Pro:~ ozgurcengelli$ pyenv versions  
* system (set by /Users/ozgurcengelli/.python-version) #look the path  
  3.6.15  
Ozgurs-MacBook-Pro:~ ozgurcengelli$ pyenv global 3.6.15  
Ozgurs-MacBook-Pro:~ ozgurcengelli$ pyenv versions  
* system (set by /Users/ozgurcengelli/.python-version) #look the path  
  3.6.15  
Ozgurs-MacBook-Pro:~ ozgurcengelli$ rm $HOME/.python-version  
Ozgurs-MacBook-Pro:~ ozgurcengelli$ pyenv versions  
  system  
* 3.6.15 (set by /Users/ozgurcengelli/.pyenv/version) #look the path  

Upvotes: 2

hlopezvg
hlopezvg

Reputation: 595

MacOSX 10.15.17

vim ~/.zshrc

Add or update

eval "$(pyenv init --path)"

Then run

source  ~/.zshrc

pyenv global 3.7.0

finally run

python -V
Python 3.7.0 (default, Dec 12 2021, 13:40:24) 

Upvotes: 23

Taku
Taku

Reputation: 5918

None of the above answers worked. It looks like I didn't follow the correct installation process. I solve it by doing the below:

  1. Go into ~/.zshrc
  2. Add alias brew='env PATH="${PATH//$(pyenv root)\/shims:/}" brew' at the end of the file
  3. Run pyenv init

More about this in the pyenv docs

Upvotes: 0

Ian Smith
Ian Smith

Reputation: 1207

[ November 2021 ]

This is what fixed the issue for me on Mac OSX with ZSH. pyenv does a bad job about explaining what needs to be added to the zsh config. $PYENV_ROOT was not defined. Order is important.

Add this near the top of your ~/.zshrc config:

export PATH="$HOME/.pyenv/bin:$PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH"
PYENV_ROOT=$(pyenv root)

Upvotes: 8

Joey Iglesias
Joey Iglesias

Reputation: 551

I have struggled with the same issue on an Apple M1 MacBook Pro running Monterey with Pyenv installed on a Rosetta emulation terminal.

My solution was to add the following to my ~/.zshrc file:

eval "$(pyenv init -)"
eval "$(pyenv init --path)"

I added nothing to ~/.zprofile.

I can now see the versions switching as expected.

Upvotes: 25

Ax_
Ax_

Reputation: 997

In the initial question I see MacOS and Pyenv installed with Homebrew. For the shell I assume is Zsh so one should have:

into file ~/.zprofile this following line

eval "$(pyenv init --path)"

And into file ~/.zshrc this following line

eval "$(pyenv init -)"

Make sure that your terminal app runs the shell as a login shell.

For other versions I suggest to see README and post-installation steps

Upvotes: 4

untidyhair
untidyhair

Reputation: 3642

[July 2021]
If you see this message when running eval "$(pyenv init -)"

WARNING: `pyenv init -` no longer sets PATH.
Run `pyenv init` to see the necessary changes to make to your configuration.

you should check the message from pyenv init as the warning says, but in a nutshell, you can use eval "$(pyenv init --path)" instead.

And don't forget to accordingly update your ~/.bash_profile, ~/.zprofile, ~/.bashrc, ~/.zshrc or the like if necessary.

Upvotes: 339

huhu78
huhu78

Reputation: 389

Assuming you're MacOS user...

Run

pyenv init

to get this tip:

# See the README for instructions on how to set up
# your shell environment for Pyenv.

So, go to https://github.com/pyenv/pyenv#readme to get this tip:

For Zsh:

MacOS, if Pyenv is installed with Homebrew:

echo 'eval "$(pyenv init --path)"' >> ~/.zprofile
 
echo 'eval "$(pyenv init -)"' >> ~/.zshrc

Make sure that your terminal app runs the shell as a login shell.

Works for me with macOS Monterey 12.0.1 and pyenv 2.2.0. Pyenv installed with brew and python installed with pyenv install.

Upvotes: 1

crifan
crifan

Reputation: 14318

Background

  • now: 20210926
  • Mac: 10.15.7
  • pyenv: 2.0.7

Solution

for current console
eval "$(pyenv init --path)"
for work after every boot

if you want auto take effect after Mac boot, then add it to you boot script

here my is zsh, so:

vi ~/.zshrc

add

eval "$(pyenv init --path)"

done.

Upvotes: 13

A. K.
A. K.

Reputation: 38098

There are situation where one cannot update ~/.bashrc or ~/.bash_profile because the machine is shared. In that case adding eval "$(pyenv init --path)" to the bash script should still work, because pyenv init adds the path to pyenv shims to the $PATH. e.g., pyenv will execute a command like this:

export PATH="/path/to/.pyenv/shims:${PATH}"

Hope this explains why it is working. Alternatively, one should be able to just export the /path/to/.pyenv/shims in their bash script and it should enable pyenv to switch python versions.

I was also facing a situation where eval "$(pyenv init -)" indeed helped switch python version to 3.8.8. But when I started a virtual environment, the python version inside the virtual environment creation would fail:

virtualenv "$VENV_PATH" -p 3.8.8

RuntimeError: failed to find interpreter for Builtin discover of python_spec='python3.8.8'

But with eval "$(pyenv init --path)" the virtual environment also got the 3.8.8. version of python.

Upvotes: 2

Boby
Boby

Reputation: 896

For me, this worked on MacOS with ZSH after installing via Homebrew:

echo 'eval "$(pyenv init --path)"' >> ~/.zprofile

I initially had eval "$(pyenv init -)" inside of my ~/.zshrc file, but that didn't seem to work. After following this guide: https://github.com/pyenv/pyenv#basic-github-checkout I remved the eval call from the .zshrc file and added it to the .zprofile file using the above command and after restarting terminal everything worked.

Upvotes: 74

Jon Weers
Jon Weers

Reputation: 1631

Run pyenv init and do exactly what it tells you to do.
For me, the solution was adding the following to .profile:

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

And also adding this line to .bashrc:

eval "$(pyenv init -)"

Don't forget to restart your shell. (Close and reopen or exec "$SHELL")

Upvotes: 8

Manjusha Nair
Manjusha Nair

Reputation: 21

If the Readme here doesn't work: https://github.com/pyenv/pyenv

Double check if you've set path before manually. In my case I added alias to old python in my .zshrc file and after removing it worked fine!

Upvotes: 1

samwize
samwize

Reputation: 27353

Check your PATH. Somehow I have .pyenv/bin, when it should be .pyenv/shims.

Fix the path with export PATH="$HOME/.pyenv/shims:$PATH" (and add to zshrc etc).

Upvotes: 5

nejdetckenobi
nejdetckenobi

Reputation: 624

Just FYI, if your executable has been found EARLIER than the pyenv's shim location then you will not be able to change python version when you type python in your shell.

To use pyenv properly, shim directory should be the very first thing in your PATH variable. For example,

if your PATH looks like

/usr/bin:/home/kenobi/.pyenv/shims:...

And if you have a python executable in /usr/bin, you will not be able to use pyenv properly. You should arrange your PATH configuration in ~/.bashrc like below

/home/kenobi/.pyenv/shims:/usr/bin:...

Then restart your shell and you'll be fine. For me, I had these lines in my ~/.zshrc

# PyEnv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"  # This line was causing the problem
eval "$(pyenv init --path)"

# Docker
export PATH=/usr/bin:$PATH
export DOCKER_HOST=unix:///run/user/1000/docker.sock

As you can see, I had export PATH=/usr/bin:$PATH after pyenv configuration lines. Then I solved the issue by switching the blocks like below

# Docker
export PATH=/usr/bin:$PATH  # Not a problem anymore.
export DOCKER_HOST=unix:///run/user/1000/docker.sock

# PyEnv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

Upvotes: 7

Edison
Edison

Reputation: 11987

If you have done pyenv local at any time in the past, it will create a new .python_version file in your home directory ~.

If your development environment is not configured properly, that could affect the pyenv global command.

Remove this file and pyenv global should work.

Upvotes: 1

Maddy
Maddy

Reputation: 521

After installing the correct version, close all terminals and try pyenv global 3.7.2 then try python --version, it should work

Upvotes: 1

Diego Ubirajara
Diego Ubirajara

Reputation: 2478

Try this: eval "$(pyenv init -)"

Example:

$ python -V
Python 2.7.9
mac:~ $ eval "$(pyenv init -)"
mac:~ $ python -V
Python 3.5.0

More info: https://github.com/pyenv/pyenv

Upvotes: 231

alien_frog
alien_frog

Reputation: 647

You forgot to add this eval "$(pyenv init -)".

Add this to your .bash_profile or .bashrc file (mac <=10.14) or to your .zshrc file (mac 10.15+)

Upvotes: 37

Powers
Powers

Reputation: 19308

This is a great opportunity to learn about how pyenv works under the hood.

The pyenv global command simply reads the data in your /Users/Soma/.pyenv/version directory. It's basically the same as cat /Users/Soma/.pyenv/version.

The pyenv versions command is just checking through the hierarchy and selecting the right Python version to use when a "shim interceptable" command like python or pip is run.

When you run pyenv global 3.5.0, the /Users/Soma/.pyenv/version file is updated to contain "3.5.0". That's the only change pyenv makes. Most users are surprised that pyenv global 3.5.0 only changes a single line in a text file!

When you run python --version, your Terminal will perform the same steps it performs when any shell command is executed: it goes through each directory in your PATH and looks for the first executable named python.

If you type echo $PATH, you'll have something like this: /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

Your machine is finding the python executable in the /usr/bin directory.

You can add this code to your ~/.bash_profile file to change your PATH.

if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi

Restart your terminal, run echo $PATH again, and you'll now see output like this: /Users/Soma/.pyenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

Notice how the /Users/Soma/.pyenv/shims directory is at the start of the PATH now. When you run python --version now, the command will be handled by the python executable in /Users/Soma/.pyenv/shims. The command won't have an opportunity to be picked up by /usr/bin/python because it'll be grabbed by /Users/Soma/.pyenv/shims/python first.

I can see why this bug confuses you. It's hard to debug this unless you know how pyenv works.

Upvotes: 30

Adam
Adam

Reputation: 388

I ran into the same problem and ended up making some changes to the way pyenv init goes about setting up the shell but in the end it works the same. The only real difference from the guide on the pyenv github page is that I had to add the $(pyenv root)/bin directory to my path too.

The reason I did this was to avoid long shell startup times from running eval "$(pyenv init -)" and all the other .bash_profile work that goes into my local shell environment. Just to be clear; Pyenv itself doesn't create a bad shell experience, in my humble opinion, but when you work with several languages that all have their own version management systems and tools that like to be initialized from the .profile with pyenv, etc., the shell initialization process can get slow.

Here's the steps I took to set myself up, at a high view:

  1. Run the dry-run version of the pyenv init command so you can see what it would have done for you.
  2. Put the PATH and shell environment vars into your .bash_profile (or whatever file your distro uses).
  3. Put the function pyenv init printed into your .bashrc and source your .bashrc from your .bash_profile

This is one way to get it done but it's better to use this as "pseudo-code". You should exchange .bash_profile for whatever file your distro prefers.

$ pyenv init - # use the output for reference, it doesn't actually do anything
$ cat <<EOBP > ~/.bash_profile
export PYENV_SHELL=bash
PATH=$(pyenv root)/shims:$(pyenv root)/bin:$PATH
[ -f  /usr/local/Cellar/pyenv/1.2.9/completions/pyenv.bash ] && . /usr/local/Cellar/pyenv/1.2.9/completions/pyenv.bash
[ -f ~/.bashrc ] && . ~/.bashrc
EOBP

The next bit updates your shell with a new bit of logic that we copied from the pyenv init dry run from step 1, above.

$ cat <<EORC > ~/.bashrc
# from $(pyenv init -)
pyenv() {
    local command
    command="${1:-}"
    if [ "$#" -gt 0 ]; then
        shift
    fi

    case "$command" in
    rehash|shell)
        eval "$(pyenv "sh-$command" "$@")";;
    *)
        command pyenv "$command" "$@";;
    esac
}
EORC

Upvotes: 1

Joe
Joe

Reputation: 492

This answer is only for people that are using Fish shell and find this thread. Pyenv uses shims, ref, so in order to make pyenv work with your fish shell you have to edit your ~/.config/fish/config.fish file an append the pyen shim directory at the beginning of your $PATH variable. Here is what my config.fish looks like.

### PATH ###
set default_path /usr/local/bin /usr/bin /usr/sbin /bin /sbin
set macports /opt/local/bin
set androiddev ~/Android\ Development/platform-tools/
set rbenv ~/.rbenv/shims/
set pyenv ~/.pyenv/shims/
set anaconda /Users/m4punk/anaconda/bin/
set pg_config /Applications/Postgres.app/Contents/Versions/9.5/bin/


### Virtual Enviroment Wrapper ###

set -g VIRTUALFISH_HOME ~/Documents/Coding/python/virtualenvs
set -g VIRTUALFISH_DEFAULT_PYTHON /usr/local/bin/python3
eval (python -m virtualfish)

### NVM Settings ###
set -g NVM_DIR ~/.nvm

set -gx PATH $pyenv $default_path $macports $androiddev $rbenv $pg_config

setenv EDITOR sublime

The relevant lines here are

set pyenv ~/.pyenv/shims/

and

set -gx PATH $pyenv $default_path $macports $androiddev $rbenv $pg_config

The first creates a variable for the pyenv shim path, the second adds it to the front of your path variable. Just save&close, restarted your terminal session and you should be all set.

Upvotes: 2

Related Questions