Updating Python to version 3.12 on Ubuntu

Published 1/7/2024 9:19:08 AM
Filed under Python

Ubuntu comes with a default version for Python, which is 3.10 for the latest LTS 22.04. The active support for this version ended in April last year. It still gets security updates, which is fine, but I want to keep up-to-date with the latest versions. In this guide, we'll take a look at setting up the latest version of Python on Ubuntu 22.04.

Installing a newer version of Python isn't straightforward on Ubuntu. You need to perform two installation steps:

  1. First, you must set up a new APT repository and install your desired Python version.
  2. Next, you must use update-alternatives to configure Ubuntu to use the latest Python version.

Let's get started by setting up the APT repository

Installing Python 3.12 with Aptitude

To install Python 3.12 on Ubuntu, you have two options: Build it from sources or download it from the Deadsnakes packages repository.

The people over at Deadsnakes offer pre-built packages for recent Python versions for Ubuntu and other Linux distributions. It's nice because compiling takes a long time and is not for everyone.

To use the Deadsnakes repository, you'll need to set it up with the following command:

sudo add-apt-repository ppa:deadsnakes/ppa

The add-apt-repository command adds a new file in /etc/apt/sources.list.d/ pointing to the Deadsnakes repository.

Because you've just added a new package repository source, you'll need to sync the APT database with the command:

sudo apt update

After synchronizing the APT database, execute the following command to install Python 3.12:

sudo apt install python3.12 python3.12-dev python3.12-venv python3.12-distutils

This command installs the Python 3.12 executables, the tools needed to work with native Python packages that use C, and the venv package you need to create virtual environments with Python 3.12. It also installs the distutils needed to install pip packages in Python 3.12.

When the installation is finished, you can verify that everything works by executing python3.12 --version. It should produce the following output:

Python 3.12.1

Now that we've finished installing Python 3.12, let's set things up so you can type python and get a Python 3.12 interpreter instead of the default Python 3.10 version.

Updating alternatives to use Python 3.12

Ubuntu uses update-alternatives to manage alternative versions for various commands. You can manage things like Java, Python, Lua, Node, and other tools with it. It works like this:

  1. In the /usr/local/bin directory, there's a symlink that points to the /etc/alternatives/ directory.
  2. The symlink in the /etc/alternatives directory points to the actual version of your tool.

The files in /etc/alternatives are managed by the update-alternatives tool. The /usr/local/bin folder is managed by a root user. Often, this is you in front of the computer.

For the python command to point to the new 3.12 version, we first introduce the new version to update-alternatives. Use the following command to do so:

sudo update-alternatives --install /usr/local/bin/python python /usr/bin/python3.12 2

This command works as follows:

  1. We want to create a master link /usr/local/bin/python
  2. The master link is part of the group of alternatives for python
  3. The master link should point to /usr/bin/python3.12
  4. The master alternative has priority 2

Introducing an alternative is not enough to make it the default. For that we need to call the following command:

sudo update-alternatives --config python

The command will ask you to choose an alternative. In my case this looks like this:

There are 3 choices for the alternative python (providing /usr/local/bin/python).

  Selection    Path                 Priority   Status
  0            /usr/bin/python3.12   2         auto mode
  1            /usr/bin/python3.10   2         manual mode
  2            /usr/bin/python3.11   2         manual mode
* 3            /usr/bin/python3.12   2         manual mode

Press <enter> to keep the current choice[*], or type selection number:

You can enter a number for the alternative you want to use. I've already set mine to 3.12, as you can see from option 0 points to Python 3.12.

After setting the alternative, you will have the python command point to Python 3.12.

There's one more step that we need to perform. We need to make sure that the pip command also uses the correct Python version.

Updating pip to use the correct Python version

We updated the /usr/local/bin/python command in the previous section to point to the latest Python version. There's a catch: We haven't touched pip, the Python package manager. It still points to the old Python version.

You can see what's going wrong here by running cat pip. It will print the contents of the pip script, which looks like this:

# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == "__main__":
    sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0])

The first line in the script tells you which interpreter it should use. It's using the /usr/bin/python3 command. That's not the one we just updated!

Unfortunately, the makers of Ubuntu didn't use the alternative mechanism for the python3 executable. Let's use the update-alternatives command to set up an alternative for python3.

sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 2

As this is the first alternative for python3 we don't need to configure anything. It's ready to go. You can now install pip packages by running pip install <package>.

After writing this post I discovered that on Ubuntu they have a pretty strange setup going on with pip. I ended up with a broken pip installation that at first seemed to work. To fix the installation, please run the following command to upgrade pip to the correct version:

python -m ensurepip --upgrade


In the previous sections, we covered how to set up the latest version of Python on Ubuntu using pre-built packages from the Deadsnakes repository. Next, we covered how to set up the correct alternative for Python on Ubuntu so that the new Python version is the default.

I recommend using an approach with pre-built packages like this because it lets you easily keep up to date with the latest patches, which is more challenging when you build Python from source code.

Using update-alternatives to manage different Python versions takes a little more work. But it allows you to switch versions if you have to. Also, you still have access to other versions by using their respective executables directly.

I hope you enjoyed this post. Let me know how you manage your Python versions!