Updated to Python 3.7.0 on Oct 12, 2018
In this setup, I'm using a vagrant machine but you don't necessarily need to do the same thing. Technically these procedures will apply to any computer running Centos 7. For the purpose of development, however, which is what this post is intended for, I highly recommend using vagrant. It makes working with development VMs so much easier.
I'd also like to mention that the approach we are taking here is to build Python 3 from source and locally in your home folder. For me, it's always good practice to have a separate Python installation from the one used by the system. It just takes away any dependencies and potential show stoppers. You might think that this sounds similar to a Docker use case but that is not what we are after here. What we are presenting here is a bare minimum approach without adding another layer of complexity.
NOTE: all commands you are expected to type are in bold.
Before we start I'd like to make sure you have an updated system.
[vagrant@localhost ~]$ sudo yum update -y
Step 1. Install yum-utils. This package is required for installing the Python dependencies in the next step.
[vagrant@localhost ~]$ sudo yum install yum-utils
Usually, it is already installed however we need to make sure.
Step 2. Install the Python dependencies. This will install all packages necessary to build Python from source.
[vagrant@localhost ~]$ sudo yum-builddep python -y
Step 3. Download the latest Python source tarball. At the time of this writing the latest one is 3.7.0.
[vagrant@localhost ~]$ curl -O https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz
Please note that you can find the latest Python release at https://www.python.org/downloads/source. For example, if there's already Python version 3.7.3 then you can update the above command to:
curl -O https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz
Step 4. Before we proceed with compiling our source let's create the folder for our local Python installation.
[vagrant@localhost ~]$ mkdir -p ~/usr/local
NOTE: -p just means to dynamically create any required parent folders for the directory path. As we are creating ~/usr/local and ~/usr does not exist, it will go ahead and create it as well.
Ensure that the directories were created.
[vagrant@localhost ~]$ ls ~/usr/
You should see the local directory.
Step 5. Extract the Python 3 source tarball.
[vagrant@localhost ~]$ tar -zxvf Python-3.7.0.tgz
After this process is done you should see a folder with the same name as the tarball. Change directory into it.
[vagrant@localhost ~]$ cd ./Python-3.7.0/
Step 6. Now we can start to compile the source. We will configure and install our own local installation of Python 3
[vagrant@localhost Python-3.7.0]$ ./configure [vagrant@localhost Python-3.7.0]$ make altinstall prefix=$HOME/usr/local exec-prefix=$HOME/usr/local
This will make sure that the root of our Python 3 installation will be at the directory we created earlier ~/usr/local.
After it's done you should see something similar to the below output:
Collecting setuptools Collecting pip Installing collected packages: setuptools, pip Successfully installed pip-10.0.1 setuptools-39.0.1
We can now go check to see if the installation is working.
[vagrant@localhost ~]$ python3 -bash: python3: command not found
As you can see here, if you just go ahead and type python3, it wouldn't recognize it. This is because we need to tell Linux where to find our Python 3 binaries and other executables, which leads us to our next step.
Step 7. We need to update our $PATH variable to include the directory where Python 3 is. In our case it will be $HOME/usr/local/bin. If you go check this directory you will see Python 3 lives there. So let's tell Linux to look there first.
As a pre-check let's see what our $PATH variable contains at the moment. Here is what I have.
[vagrant@localhost ~]$ echo $PATH /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin
You should get something pretty similar.
Alright let's go ahead with editing our ~/.bashrc file. In this case we only need to append to the file.
[vagrant@localhost ~]$ echo "export PATH=\$HOME/usr/local/bin:\$PATH" >> ~/.bashrc
NOTE: I'm using the default shell bash in this example. In any case you are using something different, you'll have to set it accordingly with the appropriate rc file. Also, the backslashes ("\") are just to stop the shell from expanding (interpolating) the $HOME and $PATH variables, so that they get written as is. This is not required, you can try to remove the backslashes if you want but I do this way so my ~/.bashrc file is more readable.
Now let's re-run our ~/.bashrc file
[vagrant@localhost ~]$ source ~/.bashrc
Step 8. Another thing we need to do aside from telling Linux where to look is to create a shorthand for whatever our Python 3 version is (in this case it's python3.7) to just python3. I don't want to be typing python3.7 all the time, I'm pretty sure you don't want to as well.
Let's go to the directory where our Python binary is.
[vagrant@localhost ~]$ cd ~/usr/local/bin/
Then let's create a symbolic link for it.
[vagrant@localhost bin]$ ln -s ./python3.7 python3
So now we can just type python3 and we are almost all set. Try it out, make sure to jump back to your home directory and run python3 from there to test if it really works. You should be able to drop to the python3 interpreter like below.
[vagrant@localhost bin]$ cd [vagrant@localhost ~]$ python3 Python 3.7.0 (default, Oct 12 2018, 13:21:48) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> exit()
Type exit() to go back to the shell.
Step 9. Create a virtualenv (virtual environment)
Aside from separating your Python installation from the one installed on the system it's definitely a must to use virtualenv's for each of your projects. To understand why just follow along.
[vagrant@localhost ~]$ python3 -m venv automate
This should create a new directory named automate. Change directory into it and activate the virtualenv.
[vagrant@localhost ~]$ cd ./automate/ [vagrant@localhost automate]$ source ./bin/activate (automate) [vagrant@localhost automate]$
This now means you are within the virtual environment automate, identified by the open and close parenthesis "( )". Inside this virtual environment, you will be running your dedicated copy of python3. All your code, when run while you are in this virtual environment will use this dedicated copy of python3. Even all the libraries and modules you will install via pip (python's package manager), will be installed only within the boundaries of this virtual environment. Let's see this in action.
(automate) [vagrant@localhost automate]$ pip freeze (automate) [vagrant@localhost automate]$ pip install netaddr Collecting netaddr Downloading netaddr-0.7.19-py2.py3-none-any.whl (1.6MB) 100% |████████████████████████████████| 1.6MB 132kB/s Installing collected packages: netaddr Successfully installed netaddr-0.7.19 (automate) [vagrant@localhost automate]$ pip freeze netaddr==0.7.19 (automate) [vagrant@localhost automate]$
NOTE: I used pip freeze to show any installed modules.
To exit the virtualenv just run deactivate and you should see it revert back to the normal shell prompt.
(automate) [vagrant@localhost automate]$ deactivate [vagrant@localhost automate]$
NOTE: It is also possible to turn an existing directory to a virtualenv instead of dynamically creating it. Below is an example.
[vagrant@localhost automate]$ cd [vagrant@localhost ~]$ mkdir automate2 [vagrant@localhost ~]$ cd ./automate2 [vagrant@localhost automate2]$ python3 -m venv . [vagrant@localhost automate2]$ source ./bin/activate (automate2) [vagrant@localhost automate2]$
As you can see we created the virtualenv while we are within the target directory (the dot "." says we are creating it here in this directory, as it would in any kind of unix speak).
So that's about it for our Python 3 installation for development step by step. I hope you were able to follow along without any issues. I tried to break it down into easy steps. If you have any questions or comments let me know by getting in touch through my contacts.