What is the proper way to manage multiple python versions?

Changing the default Python (or Perl, etc) on an OS is really bad idea. This interpreter is actually part of the OS and there may well be other OS components that are written specifically to work with that version of the interpreter.

For example on Redhat the yum tool that performs system software updates is a python application. You really don't want to break this. Such applications may depend on specific, perhaps non standard, python modules being installed which the version you installed may not have. For example on Ubuntu I believe some of the built-in OS tools written in Python use an ORM called Storm that isn't part of the Python standard library. Does your clean Python 2.7 install have the specific expected version of the Storm module installed? Does it have any version of Storm? No? Then you've just broken a chunk of your OS.

The right way to do this is install your preferred version of python and set up your user account to use it by setting up your .bash_profile, path and such. You might also want to look into the virtualenv module for Python.


How do I fix this mess?

Nothing more than reinstalling python. It will undo your change (the symlink).

Why do you want it as default? Each time you need it, just use python2.7 or include #!/usr/bin/python2.7 (the shebang) at the beginning of your (executable) scripts.

If you insist on having python2.7 as system-wide default, use a later release of Ubuntu (currently it's Ubuntu 11.04, codenamed Natty). It uses that version as default.

In future, avoid doing manual interventions like what you did with the symlink thing. This is especially true for distro-managed files, and most especially for complex beasts like Python installations.


pyenv

https://github.com/pyenv/pyenv

Pyenv allows you to manage multiple Python versions without sudo for a single user, much like Node.js NVM and Ruby RVM.

Install Pyenv:

curl https://pyenv.run | bash

Then add to your .bashrc:

export PATH="${HOME}/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

Find Python version to install:

pyenv install --list

Install the python version you want:

# Increase the chances that the build will have all dependencies.
# https://github.com/pyenv/pyenv/wiki/Common-build-problems
sudo apt build-dep python3
sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
  libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
  xz-utils tk-dev libffi-dev liblzma-dev python-openssl git

# Build and install a Python version from source.
pyenv install 3.8.0

List available Python versions:

pyenv versions

We now have:

* system (set by /home/cirsan01/.pyenv/version)
  3.8.0

Select a different python version:

pyenv global 3.8.0
python --version
python3 --version

Both output:

Python 3.8.0

We can now proceed to install and use packages normally:

pip install cowsay
python -c 'import cowsay; cowsay.tux("Python is fun")'
cowsay 'hello'

We can confirm that everything is locally installed in our clean environemnt with:

python -c 'import cowsay; print(cowsay.__file__)'
which cowsay

Per project usage

In the previous section, we saw how to use pyenv in a global setup.

However, what you usually want is to set a specific python and package version on a per-project basis. This is how to do it.

First install your desired Python version as before.

Then, from inside your project directory, set the desired python version with:

pyenv local 3.8.0

which creates a file .python-version containing the version string.

And now let's install a package locally just for our project: TODO: there is no nice way it seems: https://stackoverflow.com/questions/30407446/pyenv-choose-virtualenv-directory/59267972#59267972

Now, when someone wants to use your project, they will do:

pyenv local

which sets the Python version to the correct one.

Related threads:

  • https://askubuntu.com/questions/682869/how-do-i-install-a-different-python-version-using-apt-get
  • What is the proper way to manage multiple python versions?
  • https://stackoverflow.com/questions/10960805/apt-get-install-for-different-python-versions/59268046#59268046

Tested on Ubuntu 18.04, pyenv 1.2.15.