notice-icon

There are a number of subtle differences to managing versions of Python on older distributions of Ubuntu. If you're running Ubuntu 18.04 or older, go here.


One of my earliest frustrations with Python development had nothing to do with Python itself, but rather the needlessly esoteric act of deploying a Python app. Code bootcamps and tutorials do a fine job of teaching students how to run Python code locally, but the most meaningful applications don't run on local machines: they run on servers, on the internet, because that's the point, isn't it? Maybe I'm taking crazy pills here.

Ubuntu 20.04 is the first LTS version of Ubuntu to drop Python2, coming fresh out of the box with Python 3.8.5. But what if you've written apps intended for a newer version of Python? If you're like me, you might have tried to replace your system's default installation and destroyed your machine in the process. In case nobody has told you not to do that, I'll do the honors: don't do that.

So what do we do? There are a couple of ways to go about getting an updated version of Python on Ubuntu, but using Ubuntu's built-in "alternative install" is optimal for a number of reasons:

  1. We want to leave our system version of Python intact.
  2. It's best to avoid messing around with your Python PATH whenever possible.
  3. We can easily switch the active version of Python on our machine via a convenient CLI.

We're going to walk through how to install the current latest version of Python alongside Ubuntu's system Python versions safely and easily.

Downloading the Latest Python Version

The first step should be familiar: we need to update Ubuntu's mirrors and packages to make sure we pull the latest packages when we install anything:

$ apt update && apt upgrade -y
Obligatory updates

Installing Python fresh on a Ubuntu machine requires us to install a whole bunch of prerequisite libraries that Python depends on. I'm honestly not even sure what half of these do, and neither of us will probably ever need to. Trust me, it' a required step:

$ sudo apt-get install build-essential checkinstall
$ sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev \
    libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev
Install Python dependencies

This is where a lot of people might turn to installing Python via Ubuntu's package manager with apt-get install python3.X. We're going to download and build the latest Python version from source, for a number of reasons. If a Python version is new enough, some Ubuntu machines might have the updated mirrors necessary to find the latest version More importantly, it's easier to manage multiple Python installations this way.

The latest version of Python can always be found on the Python Source Releases page on Python.org:

Python Source Releases for Source release
The official home of the Python Programming Language

The first link on the above page should read Latest Python 3 Release - Python 3.X. On that page, scroll to the "files" section and copy the URL of the Gzipped source tarball.

On your Ubuntu machine, you're going to fetch the Python source from the URL you copied with wget. The lines below will download a compressed Python 3.9.2 archive to your /opt folder and unzip it:

$ cd /opt
$ sudo wget https://www.python.org/ftp/python/3.9.2/Python-3.9.2.tgz
$ sudo tar xzf Python-3.9.2.tgz
Download Python

The latest version of Python is now downloaded. Now we just need to install it... correctly.

Installing Alternative Python from Source

The frustration of installing Python with apt-get install python3.X is that it'll install Python just fine, but Ubuntu will still default to using whichever version of Python is the default. Luckily for us, Ubuntu allows us to install additional (AKA: alternative) versions of Python by providing us with the make altinstall command:

$ cd Python-3.9.2
$ sudo ./configure --enable-optimizations
$ sudo make altinstall
Install from source

This may take a moment to complete. Once complete, you should see python3.9 in your /usr/local/bin/ directory:

$ cd /usr/local/bin/
$ ls
Validate Python version

Managing Alternative Python Installations

So, we now have two versions of Python installed on our machine: the system default Python 3.8.5, and now our newly added Python 3.9.2. We want to leave our system default Python installation alone, but we want to run our apps written in Python 3.9... so how do we manage this?

Linux has us covered in this scenario with the update-alternatives command. We can tell Ubuntu that we have a bunch of alternative versions of the same software on our machine, thus giving us the ability to switch between them easily. Here's how it works:

$ update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1
$ update-alternatives --install /usr/bin/python3 python3 /usr/local/bin/python3.9 2
Set alternative versions for Python

We ran update-alternatives twice: once for Python 3.8, and once for Python 3.9. Now we can use update-alternatives --list to list all the alternative installations we have of certain software:

$ update-alternatives --list python3
/usr/bin/python3.6
/usr/local/bin/python3.8
List installed versions of Python

Now we can swap between versions of Python! Run the following:

$ update-alternatives --config python3
Swapping between versions

You should be hit with a prompt like the one below. This will list all the versions of Python your system recognizes. Select the version of Python you'd like to use by providing the "selection" number to the prompt:

There are 2 choices for the alternative python3 (providing /usr/bin/python3).

  Selection    Path                      Priority   Status
------------------------------------------------------------
  0            /usr/local/bin/python3.9   2         auto mode
* 1            /usr/bin/python3.8         1         manual mode
  2            /usr/local/bin/python3.9   2         manual mode

Press <enter> to keep the current choice[*], or type selection number:
CLI for switching active Python version

And you've done it! To switch Python versions, all you need to do is respond to the above prompt with the selection number representing the Python version you want to use.

It sounds absurd, but succeeding at changing Python versions in Ubuntu without breaking things is fairly impressive. I'd argue this is mostly the fault of those who teach Python. If "those who can't do, teach," it's fair to assume a lot of Python courses are taught by those who haven't launched meaningful software. That was harsh, but don't @ me regardless.

We've done the "hard" part, but there's a bit of housekeeping to take care of. We still need to install pip for our newly installed Python, as well as upgrade pip to the latest version:

$ apt install python3-pip
$ python3.9 -m pip install --upgrade pip
Install pip3

Final Tip

You've surely noticed that Ubuntu 20.04 (and newer) forces us to explicitly specify python3 when referring to Python, despite the lack of Python 2 on these machines. This is mildly annoying, but also has the potential to break libraries which look for Python (NPM packages sqlite and node-gyp are a few examples).

You may be feeling clever enough to define an alias pointing python to python3 here, but this unfortunately won't work the way you'd like. The good news is there's an easier solution:

$ apt-get install python-is-python3 
Tell Ubuntu that python is python3

Yes, there is an entire Ubuntu package out there that exists solely to resolve these issues. But hey, it works ¯\_(ツ)_/¯.