Bootstrap FreeKB - Python (Scripting) - Install Python on Linux using pyenv in a shared location
Python (Scripting) - Install Python on Linux using pyenv in a shared location

Updated:   |  Python (Scripting) articles

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.

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 Buy Me A Coffee



Comments


Add a Comment


Please enter 7009d9 in the box below so that we can be sure you are a human.