How install and use different versions of pythons on MacOS using pyenv - python

Starting out when I run $ which python3 I get:
/Library/Frameworks/Python.framework/Versions/3.8/bin/python3
And in my .zprofile I have:
PATH="/Library/Frameworks/Python.framework/Versions/3.8/bin:${PATH}"
export PATH
So starting out, I have 3.8 installed and it works. Now, I need to create a setup that will allow me to install and use different versions of python for different projects.
So, I tried the following:
$ brew update
$ brew install pyenv
$ pyenv version
It printed out System. So, it only sees the python 2.7 that comes with macos. Then I tried:
$ pyenv install 3.9.1
$ pyenv install 3.8.7
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.zshrc
$ source ~/.zshrc
Now, at the end of my .zshrc file I have:
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
But I still just get System when I run $ pyenv version. I know the different python versions are getting installed in ~/.pyenv/versions directory. So, what else am I supposed to do to get it
to list all the versions and switch back and forth between them?

First off, for pyenv to work correctly, you should uninstall the Python that's in /Library/Frameworks/Python.framework/Versions/3.8/bin/python3 and remove it from your $PATH.
If you use pyenv to manage your Python versions, then you should not install Python in any other way. pyenv will update your path automatically as you switch Python version.
Next, you need to set pyenv‘s default Python version by doing
$ pyenv global 3.9.1
on the command line.
Finally, to switch Python versions, you can use
$ pyenv local 3.8.7
on the command line. Note, that setting the local Python is sticky and works on a per-directory basis. So, for each directory where you need a specific Python version, use this command once.
For more info, see https://github.com/pyenv/pyenv/blob/master/COMMANDS.md

Related

pip install "moduleNotFound" error in .venv after Installing / upgrading-to Python 3.11 on macOS with pyenv

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'?

pyenv global x.x.x does not update the python version on linux

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

Unable to upgrade python 3.8 from 3.7.7 in macOS

I am getting error when I try
brew install python3
I think the warning said it all. brew link python3 will give you python 3.7.7.
If you like to use python 3.8, you can use brew install python#3.8 instead.
The best approach to manage Python versions is to follow Moshe Zadka's recommendations:
Install Python environment manager pyenv:
$ brew install pyenv
Install version version as you require using pyenv install python-version, e.g:
$ pyenv install 3.8.3
Set your global default version: using pyenv global python-version, e.g:
$ pyenv global 3.8.3
Add this version to your configuration file (.zshrc or .bash_profile which ever you use) to work correctly, e.g:
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.zshrc
Your configuration file will then be updated with the following:
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
Then you're good to go.
-enjoy Python!

Set default python with pyenv

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

Ubuntu 14.04 - Python 3.4 - pyenv: command Not Found

I am trying to create a virtual environment for Python 3.4 on a fresh install of Ubuntu Server 14.04. I following the instructions for the venv module at:
https://docs.python.org/3/library/venv.html#module-venv
I don't have a lot of Python 3.4 or Ubuntu experience.
When I type the command:
pyvenv testDir
I get back:
pyvenv: command not found
What is causing this?
Ubuntu 14.04 uses Python 2 by default, and the pyenv command does not exist in Python 2 out of the box.
You can, however, use virtualenv for the same purpose. You just need to install it!
You should:
Install Python 3 and virtualenv apt-get install -y python3 python-virtualenv
Create a Python 3 virtualenv: virtualenv -p $(which python3) testDir
Activate the virtual environment with source testDir/bin/activate
It's also possible to create virtualenv by python itself.
python3 -m venv myenv
see documentation https://docs.python.org/3/library/venv.html
It's in the package python3.4-venv (Linux Mint) or python3-venv (Ubuntu - I guess).
The advantages of venv over virtualenv are that (1) it's in vanilla Python3, (2) interpreter does retain tab-completion.
Edit the .bashrc file present in your home directory by adding below code and save the file:
# Load pyenv automatically by adding
# the following to ~/.bashrc:
export PATH="/home/'Enter systemname here'/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
After this you can now run the following command:
exec $SHELL
Now pyenv works properly

Categories

Resources