
pyenv can be used to install Python outside of the Python binaries in the /usr/bin directory. In other words, Python installed with pyenv will not interfere or mess up Python that was installed from a Linux repo using apt-get, dnf or yum.
- Install Python on Linux using pyenv in your home directory
- Install Python on Linux using pyenv in a shared location (this article)
Users shell’s can then be configured to use pyenv Python so that all Python commands run in the users shell use pyenv Python making this a nice solution for Python while not impacting the default installation of Python.
Let's start by listing the current version of Python that is installed.
~]# python --version
Python 2.7.5
Some Linux systems have both version 2 and version 3 of Python installed, so let's also check for Python 3.
~]# python3 --version
Python 3.6.8
Almost always, the Python binaries and symbolic links (more on this in a moment) are located in the /usr/bin directory.
]# ll /usr/bin/ | grep -i python
lrwxrwxrwx. 1 root root 7 Jul 9 02:24 python -> python2
lrwxrwxrwx. 1 root root 9 Jul 9 02:24 python2 -> python2.7
-rwxr-xr-x. 1 root root 7144 May 30 02:39 python2.7
-rwxr-xr-x. 1 root root 1835 May 30 02:39 python2.7-config
lrwxrwxrwx. 1 root root 16 Jul 9 02:24 python2-config -> python2.7-config
lrwxrwxrwx. 1 root root 9 Jul 9 02:24 python3 -> python3.6
-rwxr-xr-x. 2 root root 11336 May 30 07:42 python3.6
lrwxrwxrwx. 1 root root 17 Jul 9 02:24 python3.6-config -> python3.6m-config
-rwxr-xr-x. 2 root root 11336 May 30 07:42 python3.6m
-rwxr-xr-x. 1 root root 173 May 30 07:42 python3.6m-config
-rwxr-xr-x. 1 root root 3403 May 30 07:24 python3.6m-x86_64-config
lrwxrwxrwx. 1 root root 16 Jul 9 02:24 python3-config -> python3.6-config
lrwxrwxrwx. 1 root root 14 Jul 9 02:24 python-config -> python2-config
pyenv can be used to install Python outside of the Python binaries in the /usr/bin directory. In other words, Python installed with pyenv will not interfere or mess up Python that was installed from a Linux repo using apt-get, dnf or yum.
As root, let's install pyenv. This will create the hidden .pyenv directory at /root/.pyenv.
curl -fsSL https://pyenv.run | bash
There should now be a hidden .pyenv directory at /root/.pyenv.
~]$ ls -lisa /root
1928 8 drwxr-xr-x. 20 root root 4096 May 1 05:03 .
64 4 drwxr-xr-x. 56 root root 4096 May 1 05:15 ..
204475212 4 drwxr-xr-x. 14 root root 4096 May 1 05:04 .pyenv
Let's move the hidden .pyenv directory to the /usr/local/share directory.
mv /root/.pyenv/ /usr/local/share/
Let's create a group.
groupadd mygroup
And update the /usr/local/share/.pyenv to be writable by the group.
chgrp -R mygroup /usr/local/share/.pyenv
chmod -R g+w /usr/local/share/.pyenv
The hidden .pyenv directory should now be located at /usr/local/share/.pyenv.
~]$ ls -lisa /usr/local/share
1928 8 drwxr-xr-x. 20 root root 4096 May 1 05:03 .
64 4 drwxr-xr-x. 56 root root 4096 May 1 05:15 ..
204475212 4 drwxr-xr-x. 14 root mygroup 4096 May 1 05:04 .pyenv
Let's issue the following commands to make the pyenv CLI available in your shell. We don’t want to make these environment variables permanent for root because root should be configured to use the default Python installation (e.g. /usr/bin/python). We just need these variables set in our current shell session for the initial install and setup of pyenv.
export PYENV_ROOT="/usr/local/share/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"
You should now be able to use the pyenv CLI.
~]$ pyenv --version
pyenv 2.5.5
Let's list the versions of Python that can be installed with pyenv. There will be much more output than listed here. This is just a short snippet of the output.
~]$ pyenv install --list
3.12.0
3.12-dev
3.12.1
3.12.2
3.12.3
3.12.4
3.12.5
3.12.6
3.12.7
3.12.8
3.12.9
3.12.10
At this point, the /usr/local/share/.pyenv/versions directory should be empty as we have not yet installed Python using pyenv.
~]$ ls -lisa /usr/local/share/.pyenv/versions/
total 4
166209121 0 drwxr-xr-x. 2 root root 6 May 1 05:04 .
204475212 4 drwxr-xr-x. 14 root mygroup 4096 May 1 05:04 ..
Let's install a version of Python returned by the prior command. Notice that Python was installed in the /usr/local/share/.pyenv/versions directory.
~]$ pyenv install 3.12.0
Downloading Python-3.12.0.tar.xz...
-> https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tar.xz
Installing Python-3.12.0...
Installed Python-3.12.0 to /usr/local/share/.pyenv/versions/3.12.0
And update the new files in /usr/local/share/.pyenv to be writable by the group.
chgrp -R mygroup /usr/local/share/.pyenv
chmod -R g+w /usr/local/share/.pyenv
The pyenv global command show return "system" which means that "system" Python is being used (e.g. /usr/bin/python).
~]# pyenv global
system
And the pyenv versions command will show that "system" Python is being used.
~]$ pyenv versions
* system
3.12.0 (set by /usr/local/share/.pyenv/version)
Now let's use pyenv so that the python CLI will use the version of Python that we installed with pyenv.
- pyenv shell <version> - To make pyenv Python available for only your current shell session
- pyenv local <version> - To make pyenv Python available in your present working directory (and subdirectories)
- pyenv global <version> - To make pyenv Python available for your user account
pyenv global 3.12.0
Now the pyenv global command should return 3.12.0 (in this example) meaning that the python CLI is using pyenv Python version 3.12.0.
~]# pyenv global
3.12.0
And the pyenv versions command will show that Python version 3.12.0 is being used.
~]$ pyenv versions
system
* 3.12.0 (set by /home/john.doe/.pyenv/version)
And the python --version command should return the version of Python that was installed by pyenv regardless of our present working directory. Nice!
~]$ python --version
Python 3.12.0
Then let’s install the packages required by our Python scripts.
pip install --upgrade pip
pip install boto3
pip install Flask
pip install ipaddress
pip install paramiko
pip install requests
pip install ruamel.yaml
pip install pyopenssl
pip install datetime
pip install hvac
pip install jwt
pip install ldap3
pip install numpy
pip install oracledb
pip install ordered-set
pip install pandas
We can now exit as root. By the way, if you were to reconnect as root, the which command can be used to confirm that root is not using pyenv Python which is exactly what we want. We want root to using /bin/python.
[root@localhost]# which python
/bin/python
Let's add a couple users to mygroup.
usermod -aG mygroup john.doe
usermod -aG mygroup jane.doe
Now let's connect to this server as one of these users. At this point, /usr/bin/python and /usr/bin/python3 should still be used for the user.
[john.doe@localhost ~]$ which python
/usr/bin/python
[john.doe@localhost ~]$ which python3
/usr/bin/python3
Let's determine the users shell.
[john.doe@localhost ~]$ echo $SHELL
/usr/bash
If the users shell is /bin/bash, issue the following commands to make the pyenv CLI available in your bash shell.
echo 'export PYENV_ROOT="/usr/local/share/.pyenv"' >> ~/.bashrc
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init - bash)"' >> ~/.bashrc
echo 'export PYENV_ROOT="/usr/local/share/.pyenv"' >> ~/.bash_profile
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init - bash)"' >> ~/.bash_profile
Now both ~/.bashrc and ~/.bash_profile should contain the lines that were just appended.
~]# tail -3 ~/.bashrc
export PYENV_ROOT="/usr/local/share/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"
~]# tail -3 ~/.bash_profile
export PYENV_ROOT="/usr/local/share/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"
If the users shell is /bin/sh, you may need to create the hidden .profile file in the users home directory.
[john.doe@localhost ~]$ touch $HOME/.profile
And then issue the following commands to make the pyenv CLI available in your shell.
echo 'export PYENV_ROOT="/usr/local/share/.pyenv"' >> ~/.profile
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile
echo 'eval "$(pyenv init - bash)"' >> ~/.profile
And then reload your shell.
exec "$SHELL"
Now the which command should show that you are using pyenv Python.
[john.doe@localhost ~]$ which python
/usr/local/share/.pyenv/shims/python
[john.doe@localhost ~]$ which python3
/usr/local/share/.pyenv/shims/python3
And the pyenv global command should return the version of Python that was installed in pyenv as root.
[john.doe@localhost ~]$ pyenv global
3.12.0
And the python and python3 CLIs should return the version of Python that was installed in pyenv.
[john.doe@localhost ~]$ python --version
Python 3.12.0
[john.doe@localhost ~]$ python3 --version
Python 3.12.0
If you no longer want or need a certain version of Python that was installed in pyenv, you can uninstall it.
~]$ pyenv uninstall 3.12.1
pyenv: remove /usr/local/share/.pyenv/versions/3.12.1? (y/N) y
pyenv: 3.12.1 uninstalled
Did you find this article helpful?
If so, consider buying me a coffee over at