RalphLepore.net


Installing Python 2.7.9 on Ubuntu 14.04 LTS

While working on my latest project I ran into a small problem when installing Pillow. I am running the project on Ubuntu 14.04 LTS and the default version of python on the instance is 2.7.6. When I was deploying the project via my deploy script I got a set of security problems coming from urllib3. The below stacktrace is the error Pillow was throwing while installing my requirements file.

/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:79: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
    InsecurePlatformWarning
Exception:
Traceback (most recent call last):
  File "/webapps/ralphlepore/local/lib/python2.7/site-packages/pip/basecommand.py", line 246, in main
    status = self.run(options, args)
  File "/webapps/ralphlepore/local/lib/python2.7/site-packages/pip/commands/install.py", line 324, in run
    finder=finder, options=options, session=session):
  File "/webapps/ralphlepore/local/lib/python2.7/site-packages/pip/req/req_file.py", line 135, in parse_requirements
    isolated=options.isolated_mode if options else False,
  File "/webapps/ralphlepore/local/lib/python2.7/site-packages/pip/req/req_install.py", line 220, in from_line
    isolated=isolated)
  File "/webapps/ralphlepore/local/lib/python2.7/site-packages/pip/req/req_install.py", line 79, in __init__
    req = pkg_resources.Requirement.parse(req)
  File "/webapps/ralphlepore/local/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2960, in parse
    reqs = list(parse_requirements(s))
  File "/webapps/ralphlepore/local/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2904, in parse_requirements
    "version spec")
  File "/webapps/ralphlepore/local/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2869, in scan_list
   raise ValueError(msg, line, "at", line[p:])
ValueError: ('Expected version spec in', 'Pillow=2.8.1', 'at', '=2.8.1')

Pillow uses a set of security features and relies on requests when installing. In python versions < 2.7.9 you need to install a set of extra packages (pyOpenSSL, ndg-httpsclient, pyasn1) or you can downgrade the version of requests you are using. I don't think it's a good idea to downgrade a library or be "stuck" on a specific verion so I upgraded the version of python running on the server. Since there isnt a stable version of Python 2.7.9 on the official Ubuntu repository I decided to install it by hand.

IMPORANT: You should be extremely cautious when upgrading system level packages especially if it was installed with the default O/S version. The upgrade could break other default packages installed on the server. Always make a backup of your O/S before doing any server level installs.

Python 2.7.9 Installation

I was doing the install on a brand new Ubuntu Server 14.04 LTS instance and didn't feel there was a big risk replacing the default version of Python (which was Python 2.7.6). Below is my installation instructions.

System level updates

Before you do anything you will need to ensure you have build-essentials installed as well as the system level libs that python needs to compile.

sudo apt-get install build-essential
sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev

Python download, compile and install

Once you have updated the system level libs you can now download python 2.7.9, build and compile. You will want to either create a new directory to put the tar file in or use an existing one. I stored the tar in a directory called software in my home directory.

cd ~/software
wget https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz

# Now we are going to unpack the tar and install python
tar -xvf Python-2.7.9.tgz
cd Python-2.7.9
./configure
make
sudo make install

# Restart server to ensure everything is up to date.
sudo shutdown now -r

Conclusion

I'm a big fan of being on the latest versions of everything I'm using, this ensures that I have the most stable and secure packages. This can cause problems when installing on the system level so if you are running mission critical systems you may not want to install any unsported versions. In my usecase, I was running a new server and the project is still in its early stages so I'm comfortable with the risk of something breaking.

Tags: python, devops