The opinions expressed on this blog are purely mine

Installing python 3.9 on Ubuntu 16.04 Xenial

You may find yourself in an inconvenient situation where you need to administer an Operating system that is no longer supported. In that case, the ability to patch the OS with the latest packages is fairly important. In this post, I will show you how to install the latest python & pip version on Xenial.

First, update the apt package list

                    
apt-get update
                    
                

Setup apt

Refresh local apt keys from Ubuntu key server

                    
apt-key adv --refresh-keys --keyserver keyserver.ubuntu.com
                    
                

Install software-properties-common to be able to add 3rd party repositories to apt

                    
apt-get -y install software-properties-common
                    
                

Add deadsnakes repository to apt, then run update

                    
add-apt-repository ppa:deadsnakes/ppa
apt get update                        
                    
                

Install python

Now that apt is ready, install python3.9

                    
apt-get -y install python3.9 \
                   python3.9-distutils # might come in handy when installing packages with pip
                    
                

As a next step, remove the current python3.5.x version from your machine

This step is not necessary if there was no default python3 installed on your machine
                       
apt remove python3.5-minimal -y
                    
                

Create a python3 symlink pointing the latest python version

⚠️ This step might not be enough to reference the latest python version everywhere in your system. It may break things, but most of the time should be enough.
                    
ln -sf /usr/bin/python3.9 /usr/bin/python3
                    
                

Install the matching pip version, then clean up installer

                    
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \
    && python3.9 get-pip.py \
    && rm get-pip.py
                    
                

Validate that the install was indeed successful

                    
$ which python3
/usr/local/bin/python3

$ python3 --version
Python 3.9.2

$ pip -V
pip 18.1 from /usr/local/... (python 3.9)

                    
                

As a Dockerfile

                    
FROM ubuntu:16.04

# Refresh local apt keys & update
RUN apt-key adv --refresh-keys --keyserver keyserver.ubuntu.com \
    && apt-get update -qq

# add deadsnakes ppa
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \
    software-properties-common \
    && add-apt-repository ppa:deadsnakes/ppa \
    && apt-get update

# install python
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install
    python3.9 \
    python3.9-distutils

# remove old, default python version
RUN apt remove python3.5-minimal -y

# Create a python3 symlink pointing to latest python version
RUN ln -sf /usr/bin/python3.9 /usr/bin/python3

# Install matching pip version
RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \
    && python3.9 get-pip.py \
    && rm get-pip.py
                    
                

Update - 26th Aug 2021

I have received an email which might come handy for some of you. The email is published without modification, I've only slightly changed the formatting

                  
Your March 2021 post at prodisup.com was quite helpful. Thank you for this guidance.

For now, I'm running Ubuntu 16.05 and it took two attempts to get the python 3.9 install working. Crucial was understanding that I really didn't want to follow this step: 
- Remove the current python3.5.x version from your machine.
This step is not necessary if there was no default python3 installed on your machine (or if removing it disables a lot of other things you depend on -s)
# apt remove python3.5-minimal -y

Removing python3.5 would brick the system by removing many utilities that depend on python (the -y OPTION adds insult to injury). Happily, my mistake was reversible: re-install python 3.5 and the dependent utilities using the apt log as a guide. No major harm--only an hour or two spent, plus a little time recovering from a panic attack. ;-)

Finally, I didn't want to run the newest version of python 3 and pip everywhere in my system--only for the development user. So I put the python link to version 3.9 in /usr/local/bin and aliased that link in the development user's environment.

Thanks again