Installing/upgrading Python using pyenv

I am running Red Hat Enterprise Linux 9.4 and needed to upgrade my Python version. Shown here is my current version that is installed by default on this OS:

dev@devhost:/home/dev> cat /etc/redhat-release
Red Hat Enterprise Linux release 9.4 (Plow)

dev@devhost:/home/dev> python --version
Python 3.9.18

Python 3.9.18 was released in August 2023 (link). On RHEL 9.4, Python 3.9 is the default, fully supported version of Python (link) but can support up to 3.12+. Python 3.12.4 was released in June 2024 (link).

The list of available Python versions that the pyenv tool will pull from is located here: https://www.python.org/ftp/python/

Installing Python 3.12.4 Using pyenv

pyenv simplifies the process of installing and switching between Python versions. To install pyenv as a non-root user:

curl https://pyenv.run | bash

Afterwards add the following to your .bash_profile and re-login to the shell:

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

# Restart your shell for the changes to take effect.

# Load pyenv-virtualenv automatically by adding
# the following to ~/.bashrc:

eval "$(pyenv virtualenv-init -)"

Now install the desired Python version and set it locally:

pyenv install 3.12.4
pyenv local 3.12.4

The New Python Binaries

# The new python is installed under my local non-root account
dev@devhost:/home/dev> which python
~/.pyenv/shims/python

# The new python version is shown
dev@devhost:/home/dev> python --version
Python 3.12.4

# The new python library exists under the ~/.pyenv local folder
dev@devhost:/home/dev> /home/dev/.pyenv/versions/3.12.4/bin/python3.12 --version
Python 3.12.4

# The old python binary installed with the OS is untouched
dev@devhost:/home/dev> /usr/bin/python --version
Python 3.9.18

The Output

Here is a sample output of a successful installation:

dev@devhost:/home/dev> curl https://pyenv.run | bash

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   270  100   270    0     0   1255      0 --:--:-- --:--:-- --:--:--  1255
Cloning into '/home/dev/.pyenv'...
remote: Enumerating objects: 1267, done.
remote: Counting objects: 100% (1267/1267), done.
remote: Compressing objects: 100% (698/698), done.
remote: Total 1267 (delta 747), reused 723 (delta 436), pack-reused 0
Receiving objects: 100% (1267/1267), 627.16 KiB | 7.84 MiB/s, done.
Resolving deltas: 100% (747/747), done.
Cloning into '/home/dev/.pyenv/plugins/pyenv-doctor'...
remote: Enumerating objects: 11, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 11 (delta 1), reused 5 (delta 0), pack-reused 0
Receiving objects: 100% (11/11), 38.72 KiB | 19.36 MiB/s, done.
Resolving deltas: 100% (1/1), done.
Cloning into '/home/dev/.pyenv/plugins/pyenv-update'...
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (6/6), done.
Receiving objects: 100% (10/10), done.
remote: Total 10 (delta 1), reused 5 (delta 0), pack-reused 0
Resolving deltas: 100% (1/1), done.
Cloning into '/home/dev/.pyenv/plugins/pyenv-virtualenv'...
remote: Enumerating objects: 64, done.
remote: Counting objects: 100% (64/64), done.
remote: Compressing objects: 100% (56/56), done.
remote: Total 64 (delta 10), reused 29 (delta 1), pack-reused 0
Receiving objects: 100% (64/64), 42.50 KiB | 6.07 MiB/s, done.
Resolving deltas: 100% (10/10), done.

dev@devhost:/home/dev> pyenv install 3.12.4

Downloading Python-3.12.4.tar.xz...
-> https://www.python.org/ftp/python/3.12.4/Python-3.12.4.tar.xz
Installing Python-3.12.4...
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/dev/.pyenv/versions/3.12.4/lib/python3.12/bz2.py", line 17, in <module>
    from _bz2 import BZ2Compressor, BZ2Decompressor
ModuleNotFoundError: No module named '_bz2'
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/dev/.pyenv/versions/3.12.4/lib/python3.12/curses/__init__.py", line 13, in <module>
    from _curses import *
ModuleNotFoundError: No module named '_curses'
WARNING: The Python curses extension was not compiled. Missing the ncurses lib?
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/dev/.pyenv/versions/3.12.4/lib/python3.12/ctypes/__init__.py", line 8, in <module>
    from _ctypes import Union, Structure, Array
ModuleNotFoundError: No module named '_ctypes'
WARNING: The Python ctypes extension was not compiled. Missing the libffi lib?
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'readline'
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib?
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/dev/.pyenv/versions/3.12.4/lib/python3.12/sqlite3/__init__.py", line 57, in <module>
    from sqlite3.dbapi2 import *
  File "/home/dev/.pyenv/versions/3.12.4/lib/python3.12/sqlite3/dbapi2.py", line 27, in <module>
    from _sqlite3 import *
ModuleNotFoundError: No module named '_sqlite3'
WARNING: The Python sqlite3 extension was not compiled. Missing the SQLite3 lib?
Installed Python-3.12.4 to /home/dev/.pyenv/versions/3.12.4

dev@devhost:/home/dev> pyenv local 3.12.4

dev@devhost:/home/dev>

Version Challenges with RHEL 8.6

Python 3.6.8 was released in 2018 (link). On RHEL 8.6, Python 3.6 is the default, fully supported version of Python (link). Trying to use the same instructions above to upgrade Python to any later version simply did not work, even when trying to upgrade to 3.6.9.

Note that this is not technically an upgrade of the existing Python, but a new installation in a separate folder.

But whether it was upgrading to 3.7.17 or even a minor release 3.6.9, an error similar to the following was returned:

ModuleNotFoundError: No module named '_ssl'
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?

Please consult to the Wiki page to fix the problem.
https://github.com/pyenv/pyenv/wiki/Common-build-problems


BUILD FAILED (Oracle Linux Server 8.6 using python-build 2.4.7)

Inspect or clean up the working tree at /tmp/python-build.20240712180643.3929278
Results logged to /tmp/python-build.20240712180643.3929278.log

Last 10 log lines:
                install|*) ensurepip="" ;; \
        esac; \
        LD_LIBRARY_PATH=/tmp/python-build.20240712180643.3929278/Python-3.6.9 ./python -E -m ensurepip \
                $ensurepip --root=/ ; \
fi
Looking in links: /tmp/tmpfnlpg5w0
Collecting setuptools
Collecting pip
Installing collected packages: setuptools, pip
Successfully installed pip-18.1 setuptools-40.6.2

References: