73

I want to run tests with multiple Python versions on OS X 10.11, including:

  • Python 2.6 - ?!
  • Python 2.7 - default - solved
  • Python 3.4 - ?!
  • Python 3.5 - installed via brew - works well
  • Conda Python 3.5 - ?!

I want to run the tests via tox so tox needs to be able to find them. Sadly it seems that brew doesn't want to install 3.4 since they added 3.5 and I obviously do not want to remove 3.5 one.

bfontaine
  • 18,169
  • 13
  • 73
  • 107
sorin
  • 161,544
  • 178
  • 535
  • 806
  • 2
    This may help: [Is there a python equivalent of Ruby's 'rvm'?](http://stackoverflow.com/questions/2812471/is-there-a-python-equivalent-of-rubys-rvm) – Jonathan Lonowski May 01 '16 at 15:34

8 Answers8

72

pyenv is the thing you want. It works very very well:

pyenv lets you easily switch between multiple versions of Python. It's simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well. This project was forked from rbenv and ruby-build, and modified for Python.

https://github.com/pyenv/pyenv

Install it via Homebrew:

$ brew update
$ brew install pyenv

It handles the download, compilation, and installation of various pythons for you, e.g.:

$ pyenv install 3.7.2

It can show you which versions you've installed, and which is active:

$ pyenv versions
  system
  3.6.7
* 3.7.2

When you're in a new project directory, just tell pyenv which python version to use there:

$ pyenv local 3.6.7  # Because e.g. tensorflow isn't compat. with 3.7 :-(

You can set a 'default' version everywhere else:

$ pyenv global 3.7.2
Dogweather
  • 15,512
  • 17
  • 62
  • 81
  • Also requires brew postinstall python3 so that pip3 is available. – Ayusman Mar 14 '19 at 16:59
  • 1
    in current version pip3 is directly available after you run pyenv install 3.x.y – cmlonder Jan 17 '21 at 20:29
  • 1
    pyenv or asdf cannot install m1/arm64 Python on macOS 12.x – hipertracker Jan 03 '22 at 02:01
  • pyenv is great. I have noticed one flaw - in comparison of with the 'brew solution - you can't update the version of pip coming with it. Is it correct? – Mez13 Jul 07 '22 at 17:30
  • 1
    Pyenv is great. Dont forget to add ~/.pyenv/shims to the PATH variable to pick up the pyenv version of python, so that the global set version can be picked up by default – Kira Nov 10 '22 at 05:29
49

brew alone has been sufficient for me to use multiple versions of Python. I haven't needed pyenv or conda for it.

To install various versions using brew, run commands such as:

brew install python@3.9
brew install python@3.8

When creating a virtual environment, create it using one of:

/usr/local/opt/python@3.9/bin
/usr/local/opt/python@3.8/bin

Please list the bin directory above using ls in order to find and use the python executable in it.

For macOS M1 (not Intel) (see also, M1 brew setup), modify brew install path, eg:

/opt/homebrew/Cellar/python@3.8/bin

Please list the bin directory above using ls in order to find and use the python executable in it.

Lastly, the version of /usr/local/bin/python3 is probably not the version you want for your virtual environment.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
  • @kd12345 You do not have to unlink or link to "navigate between versions". Instead use virtual environments for your projects. – Asclepius Apr 29 '21 at 01:12
  • In Big Sur (with zsh) this doesn't work for me; I get permission denied when trying to call `/usr/local/opt/python@3.8/bin`. – Leon Overweel Sep 23 '21 at 08:37
  • 1
    You don't need to avoid using python3 when creating a virtual env, since the python version inside that env will always be the same – Alex Dec 17 '21 at 17:23
  • 1
    @Asclepius I understand you're point, just saying that, as long as you know which version of python3 you're using when you create your virtual env, within that venv if you call `python3` (not with its full path), that would be the version that created that virtual env, no matter if python3 was upgraded outside that venv. – Alex Dec 20 '21 at 10:53
  • 2
    This is the correct answer. Instead of forcing any particular version, the above solution can be used to create multiple virtual environments with different python versions. – shivshankar Jan 11 '22 at 18:08
  • `-p` expects an executable AFAIK, but `/usr/local/opt/python@3.9/bin` is a folder. I'm getting the same error as @LeonOverweel – Drenai Jun 06 '22 at 12:11
  • @Drenai Please find and use the python executable in the `bin` directory you noted (using `ls`). – Asclepius Jun 06 '22 at 13:46
  • To create a venv using a Python version installed in this manner, do something like: `/opt/homebrew/Cellar/python@3.8/3.8.13_1/bin/python3.8 -m venv SomeVenv` (M1, MacOS 12.4) – James_SO Jun 09 '22 at 19:31
  • 3
    Here is how you can find the path `$(brew --prefix python@3.9)/bin` – mtmk Jul 23 '22 at 00:00
23

This blog post suggests using pyenv with the desired detox. The basic setup with brew requires:

brew install pyenv pyenv-virtualenv pyenv-virtualenvwrapper

Then installing the desired Python versions with pyenv install [version], rather than installing Python using brew. You can check the available versions using pyenv versions.

Finally, pip install detox will ensure you've got tox and detox installed. Then you should be able to specify the desired testing versions in your tox.ini.

user2943160
  • 507
  • 5
  • 12
9

As previous answers also mentioned.. no pyenv needed, this works perfect for me:

brew install python@3.7
brew install python@3.8
brew install python@3.9

Then just add the corresponding version lines to the ~/.bashrc

export PATH="$PATH:/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/bin"
export PATH="$PATH:/usr/local/opt/python@3.8/Frameworks/Python.framework/Versions/3.8/bin"
export PATH="$PATH:/usr/local/opt/python@3.9/Frameworks/Python.framework/Versions/3.9/bin"
walter
  • 539
  • 5
  • 5
  • Would you only add one of those paths in bash at a time? – Drenai Jun 04 '22 at 09:07
  • 1
    no, all at the same time. it's possible because each path has inside a bin file with different name.. e.g python3.8 – walter Jun 05 '22 at 11:36
  • +1 I just discovered `brew --prefix` .. so put his in my rc: `for pyver in 3.7 3.8 3.10 3.9; do export PATH=$PATH:$(brew --prefix python@$pyver)/bin; done` – mtmk Jul 22 '22 at 23:47
1

I'd highly recommend using a package manager such as Anaconda, https://www.continuum.io/downloads, which it makes it trivially easy to install different self-contained virtual-envs.

For example, to create a virtual environment with numpy and Python 2.7 this is the command:

conda create --name py2_env numpy python=2.7

And then to switch to that environment:

source activate py2_env

flybonzai
  • 3,763
  • 11
  • 38
  • 72
  • 1
    This is not an option because it works only with conda and I am looking for something that works with more than conda. – sorin May 12 '16 at 21:30
0

pyenv is all well and good but I feel that we should give a mention to the wonderful pipenv library from Kenneth Reitz.

https://github.com/pypa/pipenv

It provides the functionality of pyenv plus dependency locking, support for .env out-of-the-box and much more.

Carlos
  • 1,897
  • 3
  • 19
  • 37
  • 4
    Pipenv can only use the versions of python that are already installed, so that does not help with the question. – Toby Mar 13 '19 at 07:34
0

I strongly recommend DO NOT USE pyenv in most cases. You will face deep problems with pyenv - check this: https://stackoverflow.com/a/66797993/10849913

0

My understanding below may help manage different versions of python:

      python3.10 -> python3.10 has its own pip module 
                -> how to install?
                  curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
                  sudo  /opt/local/bin/python3.10  get-pip.py
                      -> package is installed based on this pip, it belong to python3.10
                        /opt/local/bin/python3.10 -m pip install pandas
                              -> package location
                              /Users/frank/Library/Python/3.10/lib/python/site-packages

      python3.9 -> python3.9 has its own pip module 
                -> how to install?                  
                  curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
                  sudo  /opt/local/bin/python3.9  get-pip.py
                      -> package is installed based on this pip, it belong to python3.9
                          /opt/local/bin/python3.9 -m pip install pandas
                              -> package location
                                /Users/frank/Library/Python/3.9/lib/python/site-packages
Frank Wu
  • 11
  • 2