CentOS 7 Python 2.7 Upgrade Deprecation Message – End Of Life January 1st, 2020

For CentOS 7 based Centmin Mod users, you may run into the Python 2.7 deprecation message when running CentOS 7 native Python 2.7 and that Python 2.7’s end of life is on January 1, 2020 and that you need to upgrade Python 2.7. You should not upgrade the CentOS 7 native Python 2.7 as that may break your system and YUM operation. Instead, you should install a newer Python version side by side.

You ran Python 2.7 via command line and got the below message. So what do you do?

DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won’t be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support

CentOS Python 2.7 usually gets backported updates to same Python 2.7 version package as would Redhat upstream Python 2.7. So that message is just cosmetic – you do not overwrite and upgrade system Python 2.7 on CentOS otherwise you break CentOS and possibly YUM itself so won’t be able to update via YUM and break any system dependencies on Python 2.7.

Python 3.6 Install

Instead, you can install Python 3.6 side by side with Python 2.7 via Centmin Mod 123.09beta01’s addons/python36_install.sh and you’d have pip3.6 and python3.6 access to 3.6 version. For non-Centmin Mod users, there’s plenty of online guides for installing Python 3.6 side by side with CentOS 7’s Python 2.7. Note: CentOS 7 only has Python version up to 3.6 installable via YUM packages. For Python 3.7 and above you may need to result to source compilations (see below).

Latest Python 3 version available in CentOS 7’s YUM repository right now is Python 3.6.8.

yum -q list python3
Installed Packages
python3.x86_64 3.6.8-18.el7 @updates

Centmin Mod CentOS 7 users can run addons/python36_install.sh installer to install Python 3.6 by side by side with CentOS 7’s Python 2.7.

/usr/local/src/centminmod/addons/python36_install.sh

Then you’d have access to both native CentOS 7’s Python 2.7 and Python 3.6

python --version
Python 2.7.5

python3.6 --version
Python 3.6.8

Then if your python app needs python 3.6, you can use virtualenv to setup sandbox for python 3.6 similar to outline at How to install the latest version of Python on CentOS – Daniel Eriksson – skip directly to section under Create your first isolated Python environment header instead though of pip2.7 it’s just pip for 1st step. There are 2 ways of creating sandboxes, virtualenv and pipenv see Pipenv & Virtual Environments — The Hitchhiker’s Guide to Python along with virtualenvwrapper

Example for virtualenv using python3.6 interpreter

pip install virtualenv
mkdir -p /home/python_projects
cd /home/python_projects
virtualenv -p /usr/bin/python3.6 venv1

Example output from virtualenv command

virtualenv -p /usr/bin/python3.6 venv1
Running virtualenv with interpreter /usr/bin/python3.6
Already using interpreter /usr/bin/python3.6
Using base prefix '/usr'
  No LICENSE.txt / LICENSE found in source
New python executable in /home/python_projects/venv1/bin/python3.6
Also creating executable in /home/python_projects/venv1/bin/python
Installing setuptools, pip, wheel...
done.

Then to activate Python 3.6 sandbox

source venv1/bin/activate

Once activated, you can update pip version within sandbox and install other Python related dependencies for your Python apps.

  • Centmin Mod uses ccache for compiler caching, which pip doesn’t like, so you disable ccache first and
  • Centmin Mod secures /tmp with noexec permissions so need to use a different temp directory for pip compilations.
  • Finally, update pip command to latest version within sandbox.
# pip doesn't like ccache so disable it
export CC='gcc'
export CXX="g++"

# pip needs a tmp directory that doesn't have noexec restrictions
mkdir -p /home/piptmp
chmod 1777 /home/piptmp
export TMPDIR=/home/piptmp

# update pip defined by -p flag to use python3.6 binary
pip install -U pip
pip --version

Example of updating pip within the Python 3.6 virtualenv project named venv1

(venv1) [02:20][root@host.domain.com python_projects]# pip install -U pip
Collecting pip
Downloading https://files.pythonhosted.org/packages/54/eb/4a3642e971f404d69d4f6fa3885559d67562801b99d7592487f1ecc4e017/pip-20.3.3-py2.py3-none-any.whl (1.5MB)
|████████████████████████████████| 1.5MB 8.5MB/s
Installing collected packages: pip
Found existing installation: pip 19.3.1
Uninstalling pip-19.3.1:
Successfully uninstalled pip-19.3.1
Successfully installed pip-20.3.3

(venv1) [02:20][root@host.domain.com python_projects]# pip --version
pip 20.3.3 from /home/python_projects/venv1/lib/python3.6/site-packages/pip (python 3.6)

The Python and pip binaries installed in virtual environment called venv1 in bin directory at /home/python_projects/venv1/bin

ls -lah /home/python_projects/venv1/bin/
total 72K
drwxr-xr-x 2 root root 4.0K Jan  5 02:20 .
drwxr-xr-x 5 root root 4.0K Dec  7  2019 ..
-rw-r--r-- 1 root root 2.2K Dec  7  2019 activate
-rw-r--r-- 1 root root 1.5K Dec  7  2019 activate.csh
-rw-r--r-- 1 root root 3.1K Dec  7  2019 activate.fish
-rw-r--r-- 1 root root 1.8K Dec  7  2019 activate.ps1
-rw-r--r-- 1 root root 1.5K Dec  7  2019 activate_this.py
-rw-r--r-- 1 root root 1.2K Dec  7  2019 activate.xsh
-rwxr-xr-x 1 root root  255 Dec  7  2019 easy_install
-rwxr-xr-x 1 root root  255 Dec  7  2019 easy_install-3.6
-rwxr-xr-x 1 root root  246 Jan  5 02:20 pip
-rwxr-xr-x 1 root root  246 Jan  5 02:20 pip3
-rwxr-xr-x 1 root root  246 Jan  5 02:20 pip3.6
lrwxrwxrwx 1 root root    9 Dec  7  2019 python -> python3.6
lrwxrwxrwx 1 root root    9 Dec  7  2019 python3 -> python3.6
-rwxr-xr-x 1 root root  12K Dec  7  2019 python3.6
-rwxr-xr-x 1 root root 2.3K Dec  7  2019 python-config
-rwxr-xr-x 1 root root  233 Dec  7  2019 wheel

Direct access to venv1 sandbox’s version of python 3.6 and pip 3.6 to install python packages will end up in /home/python_projects/venv1/ sandbox directory not to pollute system python 2.7.

(venv1) [02:24][root@host.domain.com python_projects]# /home/python_projects/venv1/bin/python3.6 --version
Python 3.6.8

(venv1) [02:26][root@host.domain.com python_projects]# /home/python_projects/venv1/bin/pip3.6 --version
pip 20.3.3 from /home/python_projects/venv1/lib/python3.6/site-packages/pip (python 3.6)

(venv1) [02:26][root@host.domain.com python_projects]# /home/python_projects/venv1/bin/pip --version
pip 20.3.3 from /home/python_projects/venv1/lib/python3.6/site-packages/pip (python 3.6)

Python 3.7+ Install

Python 3.7+ and higher would need to be source installed on CentOS 7. The source compilation can take a long time to install especially on slow servers or single cpu threaded servers – could take hours on very slow servers! So if you don’t have a specific Python 3.7+ version requirement, you might want to stick with above Python 3.6 install and virtualenv setup method.

You can see the current Python versions on official Python site. Latest versions are Python 3.7.9 for security release and for bug fix and feature releases, Python 3.8.7 and Python 3.9.1.

I’ve only tested Python 3.7, so will do example install for Python 3.7.9.

Preparations to update Centmin Mod 123.09beta01 and newer local code via cmupdate command and then disable ccache compiler caching and to setup dedicated temp directory for PIP as normal temp has noexec permissions configured.

# update Centmin Mod code
cmupdate

# pip doesn't like ccache so disable it
export CC='gcc'
export CXX="g++"

# pip needs a tmp directory that doesn't have noexec restrictions
mkdir -p /home/piptmp
chmod 1777 /home/piptmp
export TMPDIR=/home/piptmp

Install Python 3.7.9 which took ~18 minutes to compile and install on a dedicated Intel Core i7 4790K Haswell server with 32GB memory.

yum -y install libffi-devel
python_ver=3.7.9
python_prefixver=$(echo $python_ver | cut -d . -f1,2)
cd /svr-setup
wget https://www.python.org/ftp/python/${python_ver}/Python-${python_ver}.tgz
tar xzf Python-${python_ver}.tgz
cd Python-${python_ver}
make clean
if [[ "$(nproc)" -le '2' ]]; then time ./configure --prefix=/opt/python${python_prefixver} --with-openssl=/usr; else time ./configure --enable-optimizations --prefix=/opt/python${python_prefixver} --with-openssl=/usr; fi
time make -j$(nproc)
time make altinstall
ls -lah /opt/python${python_prefixver}/bin
ln -s /opt/python${python_prefixver}/bin/python${python_prefixver} /opt/python${python_prefixver}/bin/python3
ln -s /opt/python${python_prefixver}/bin/python${python_prefixver} /opt/python${python_prefixver}/bin/python
ln -s /opt/python${python_prefixver}/bin/python${python_prefixver} /usr/bin/python${python_prefixver}
ln -s /opt/python${python_prefixver}/bin/pip${python_prefixver} /opt/python${python_prefixver}/bin/pip3
ln -s /opt/python${python_prefixver}/bin/pip${python_prefixver} /opt/python${python_prefixver}/bin/pip
ln -s /opt/python${python_prefixver}/bin/easy_install-${python_prefixver} /opt/python${python_prefixver}/bin/easy_install
ln -s /opt/python${python_prefixver}/bin/idle${python_prefixver} /opt/python${python_prefixver}/bin/idle
ln -s /opt/python${python_prefixver}/bin/2to3-${python_prefixver} /opt/python${python_prefixver}/bin/2to3
ln -s /opt/python${python_prefixver}/bin/pydoc${python_prefixver} /opt/python${python_prefixver}/bin/pydoc
ln -s /opt/python${python_prefixver}/bin/pyvenv-${python_prefixver} /opt/python${python_prefixver}/bin/pyvenv
rm -f /svr-setup/Python-${python_ver}.tgz
/opt/python${python_prefixver}/bin/python${python_prefixver} --version
/opt/python${python_prefixver}/bin/pip${python_prefixver} --version

Note at make altinstall completion the message at the end will output

Installing collected packages: setuptools, pip
Attempting uninstall: setuptools
Found existing installation: setuptools 41.2.0
Uninstalling setuptools-41.2.0:
Successfully uninstalled setuptools-41.2.0
WARNING: The script easy_install-3.7 is installed in '/opt/python3.7/bin' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Attempting uninstall: pip
Found existing installation: pip 19.2.3
Uninstalling pip-19.2.3:
Successfully uninstalled pip-19.2.3
WARNING: The script pip3.7 is installed in '/opt/python3.7/bin' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed pip-20.1.1 setuptools-47.1.0

The end result are Python and pip 3.7.9 binaries at

/opt/python3.7/bin/python --version
Python 3.7.9

/opt/python3.7/bin/pip --version
pip 20.1.1 from /opt/python3.7/lib/python3.7/site-packages/pip (python 3.7)

Then to setup Python 3.7 virtual environment using a method different from Python 3.6 above outlined method via the -m env flag for /home/python_projects/myproject or whatever directory you choose

python_ver=3.7.9
python_prefixver=$(echo $python_ver | cut -d . -f1,2)
mkdir -p /home/python_projects/myproject
/opt/python${python_prefixver}/bin/python${python_prefixver} -m venv /home/python_projects/myproject

Contents of Python 3.7.9 virtual environments bin directory at /home/python_projects/myproject/bin

ls -lah /home/python_projects/myproject/bin
total 40K
drwxr-xr-x 2 root root 4.0K Jan 5 03:14 .
drwxr-xr-x 5 root root 4.0K Jan 5 03:14 ..
-rw-r--r-- 1 root root 2.2K Jan 5 03:14 activate
-rw-r--r-- 1 root root 1.3K Jan 5 03:14 activate.csh
-rw-r--r-- 1 root root 2.4K Jan 5 03:14 activate.fish
-rwxr-xr-x 1 root root 259 Jan 5 03:14 easy_install
-rwxr-xr-x 1 root root 259 Jan 5 03:14 easy_install-3.7
-rwxr-xr-x 1 root root 250 Jan 5 03:14 pip
-rwxr-xr-x 1 root root 250 Jan 5 03:14 pip3
-rwxr-xr-x 1 root root 250 Jan 5 03:14 pip3.7
lrwxrwxrwx 1 root root 9 Jan 5 03:14 python -> python3.7
lrwxrwxrwx 1 root root 9 Jan 5 03:14 python3 -> python3.7
lrwxrwxrwx 1 root root 28 Jan 5 03:14 python3.7 -> /opt/python3.7/bin/python3.7

Then to activate the sandbox virtual environment called myprojects

source /home/python_projects/myproject/bin/activate

Then within activated myproject virtual environment you can update pip

# pip doesn't like ccache so disable it
export CC='gcc'
export CXX="g++"

# pip needs a tmp directory that doesn't have noexec restrictions
mkdir -p /home/piptmp
chmod 1777 /home/piptmp
export TMPDIR=/home/piptmp

pip install -U pip

Update pip output within virtual environment

(myproject) [03:16][root@host.domain.com Python-3.7.9]# pip install -U pip
Collecting pip
Using cached pip-20.3.3-py2.py3-none-any.whl (1.5 MB)
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 20.1.1
Uninstalling pip-20.1.1:
Successfully uninstalled pip-20.1.1
Successfully installed pip-20.3.3

Then directly calling python 3.7.9 virtual environment

/home/python_projects/myproject/bin/pip --version
pip 20.3.3 from /home/python_projects/myproject/lib/python3.7/site-packages/pip (python 3.7)

/home/python_projects/myproject/bin/python --version
Python 3.7.9