Python

Object-Oriented Programming With Python : Inheritance (2/3)

Continuing on our Object-Oriented Programming with Python series, this is article 2 of 3 on the 2nd pillar, Inheritance. You can find the first article about Encapsulation in this series here.

Inheritance – The Second Pillar

Inheritance in OOP is the ability to have one class inherit the attributes of another class.

Inheritance is simple to implement, but arguably the most powerful pillar in OOP, providing the most value to a programmer. It is the pillar that allows for effective re-use of code organized in classes reducing the amount of lines a programmer has to write to do something useful in their program.

In case you don’t remember from the previous article in this series on encapsulation, a class is a blueprint or template that contains methods, objects and attributes. Once defined a class can be inherited by another class. At which point the child class (aka derived class or subclass) contains all the goodness that the parent class ( aka super class or base class) provides.

Here is an example of inheritance :

#!/usr/bin/env python

import requests

class Tuxlabs(object):

    def setter(self, website):
        if 'http' in website:
            self.website = website
        else:
            print 'ERROR: Unable to set website to %s.\nRequired format is: http://www.example.com' % (website)

    def getter(self):
        return self.website

class Crawl(Tuxlabs):

    def download(self, website):
        self.setter(website)
        crawlTarget = self.getter()
        r = requests.get(crawlTarget)
        print r.text

website = 'http://www.tuxlabs.com'
crawl = Crawl()
crawl.download(website)

The code above downloads the webpage ‘tuxlabs.com’ and outputs it’s contents to STDOUT using the ‘requests’ module.

<rant>If you are a Python developer who is not already familiar with the requests module you should be ashamed of yourself 🙂 It is the most fantastically simple implementation of Python HTTP client functions available.</end rant>

In this example we have defined two classes, one called ‘Tuxlabs’ and one called ‘Crawl’. Tuxlabs inherits a base class ‘object’ and the ‘Crawl’ class inherits ‘Tuxlabs’. If you’re wondering why Tuxlabs inherits from object see here.  Our ‘Tuxlabs’ class has two methods a setter() & a getter() you will remember from the previous article on encapsulation. Now let’s focus on the real point in this example, the ‘Crawl’ class.

The ‘Crawl’ class as previously mention inherits the Tuxlabs class when it is defined or implemented ‘class Crawl(Tuxlabs):’. This means when an instance of Crawl initialized it will inherit all the attributes from the Tuxlabs class in addition to it’s own methods defined in the ‘Crawl’ class. The ‘Crawl’ class has only one method defined ‘download’ that takes a single argument, website.

Inside the download method in the crawl class we see ‘self.setter(website)’, but this is interesting, because we are using ‘self’ to call ‘setter()’, but self is actually referring to the ‘Crawl’ class and the ‘Crawl’ class  only has download defined. So shouldn’t an error be thrown when we try to access ‘self.setter(website)’ inside the ‘Crawl’ class, when setter() lives in ‘Tuxlabs’ ?

No, and the answer is because self, which refers to our ‘Crawl’ class, which is actually inheriting from our ‘Tuxlabs’ class. So this actually works ! Now from within ‘Crawl’ we can access all methods and attributes in Tuxlabs or Crawl, nifty, handy and powerful are the words that come to mind. Before moving on to some even cooler features, let’s show the abbreviated output of this script (I can’t show the entire webpage output, yuck!).

➜  tuxlabs  python example.py 
...
</body>
</html>
➜  tuxlabs

Nothing magical there, but I did want to show you that this code works !

Now then, we should talk about __init__ & super().

__init__() if you don’t already know is the initial method called in a class. It is what other languages might refer to as a constructor. When you create an instance object of a class the __init__() method within that class is called and whatever code is in it is executed. Init can be good for setting up default/static values used within the scope of the class and other methods. A typical example of an init class might look like this.

class Foundation(object):
    def __init__(self, sqlCreds):
        self.sqlHost = sqlCreds['host']
        self.sqlUser = sqlCreds['user']
        self.sqlPass = sqlCreds['pass']
        self.sqlDb = sqlCreds['db']
        if 'port' in sqlCreds:
            self.sqlPort = int(sqlCreds['port'])
        else:
            self.sqlPort = 3306
        self.sqlQuery = ''

Here we are defining a class ‘Foundation’ and an init constructor that accepts a dictionary as an argument containing SQL Credentials. Then within the init constructor we define several attributes who’s values are populated from that dictionary. We also made ‘port’ an optional argument with a default port of ‘3306’ the MySQL default port. This is a very useful start to a class, and it is my actual code from a project. From here we would build on top of this class many other methods like SQL queries we frequently used and other data processing techniques we frequently need like parsing JSON or XML.

Now let’s assume for a moment, this is a larger scale project. One that requires many classes. Classes that are inheriting from each other. Because the ‘Foundation’ class above is so generic, it can be used over and over again in other classes. However, those other classes will have slightly different purposes. In the case of databases, perhaps each class represents a different database. This makes sense, but we would still want to make use of the lovely constructor code inside of ‘Foundation’, thanks to it’s well written generic-ness. Here is an example of how we would do that, using something called super().

class Foundation(object):
    def __init__(self, sqlCreds):
        self.sqlHost = sqlCreds['host']
        self.sqlUser = sqlCreds['user']
        self.sqlPass = sqlCreds['pass']
        self.sqlDb = sqlCreds['db']
        if 'port' in sqlCreds:
            self.sqlPort = int(sqlCreds['port'])
        else:
            self.sqlPort = 3306
        self.sqlQuery = ''
...

class Cloud(Foundation):
    def __init__(self, sqlCredsCloud):
        super(Cloud, self).__init__(sqlCredsCloud)

...

We have our original class ‘Foundation’, and a new child class ‘Cloud’ that inherits ‘Foundation’. In addition ‘Cloud’ is defining it’s own __init__ constructor and accepting a dictionary for SQL credentials ‘sqlCredsCloud’. Finally, we call super() and pass our ‘Cloud’ class to the inherited class ‘Foundation’  (in this case self) and pass our SQL Creds to the ‘Foundation’ class constructor.

Whew.. I think I did an ok job explaining that, but you may need to read it back a couple of times and re-visit after trying to use this concept. Let’s take a look at how we would use these classes.

import sys
sys.path.append('/Users/jriedel/PycharmProjects')
from mymodules import foundation

def setup_cloud_db(sqlCredsCloud):
    Cloud = foundation.Cloud(sqlCredsCloud)
    CloudCursor = Cloud.SqlConnect()

    return (CloudCursor, Cloud)

if __name__ == '__main__':
    sqlCredsCloud = {'host': 'localhost', 'user': 'root', 'pass': '', 'db': 'cloud'}
    (CloudCursor, Cloud) = setup_cloud_db(sqlCredsCloud)
    Cloud.TruncateTable('cloud_machine_counts')

First we modify our Python path to locate the foundation module and import it. Then we create a subroutine for setting up our connection to the database and creating our instance object of our Cloud class. Notice we are passing sqlCredsCloud to the Cloud class and remember internally this is passing sqlCreds to the Foundation class constructor.  Finally, in the main routine of the program, after we setup the credentials and after we setup our database connection, we call ‘TruncateTable’, which is a method within the Cloud class that I have not shown in our code above, but you get the idea. Well I think that is about all I can muster, you now know what I know about inheritance.

For more information on super() click here

See ya next time !
Jason Riedel

Object-Oriented Programming With Python : Inheritance (2/3) Read More »

Introducing Vault

Vault

Vault is a command line utility for encrypting & decrypting things. Those things are stored on disk in hidden files, meaning in *nix they simply have a ‘.’ in front and don’t show up unless you type ls -la 😉 But anyway, who cares if someone can locate the files ! They are AES encrypted !

I wrote Vault for a couple of reasons.

  1. To learn how to use encryption in Python
  2. To store passwords for stuff
  3. To turn Vault into methods in my Utilities class that I use for my daily programming activities. First write a command line utility, then write a class 🙂

Vault Usage

I literally wrote vault earlier today and even though it is super simple, I still find it cool & useful so I had to share. Here’s a demo on it’s simple usage !

Keys

AES / Vault supports 16, 24, or 32 byte encryption keys. A byte is one character. Your key should be something ambiguous that you can remember and you should not use the ‘0123…’ example below. What would really be paranoid is to encrypt your keys in a separate vault somewhere 🙂 Note, you will need to use the same key to encrypt as decrypt for a given stored piece of encrypted data.

Encrypting

➜  vault git:(master) python store.py --name tuxlabs -t 'Well I could store a password or b00bs, cause everyone likes b00bs even the newbs' --key 01234567890987654321abcd
p/hvz1hf9RIyBeyMmgL2CILvlM20vU72E075K+32tysNU8dIJOcX/gVmRISYQTp0tHZ/W+qL2mCvMFrMP3rGAV2kCNNjGQNnbUSgPibPGiqfwMrQm3/EhH/f18dZofDGTwcMmHZ3LiERuIZt1toU0w== was stored as tuxlabs
➜  vault git:(master) ✗

Can You Read The File Contents ?

➜  vault git:(master) ✗ cat .tuxlabs 
p/hvz1hf9RIyBeyMmgL2CILvlM20vU72E075K+32tysNU8dIJOcX/gVmRISYQTp0tHZ/W+qL2mCvMFrMP3rGAV2kCNNjGQNnbUSgPibPGiqfwMrQm3/EhH/f18dZofDGTwcMmHZ3LiERuIZt1toU0w==%                                                                                                                     ➜  vault git:(master) ✗

Decrypting

➜  vault git:(master) ✗ python retrieve.py --name tuxlabs --key 01234567890987654321abcd
Well I could store a password or b00bs, cause everyone likes b00bs even the newbs
➜  vault git:(master) ✗

Alternatively, you can hide the key from the command line, by not specifying it. 

➜  vault  python store.py --name JimmyJohns --text 'Really Fast'
Key:
1HHF5TPl0cklDU/TXjMQ8nFeqK4zULQ50dVpJ+apgzQ= was stored as JimmyJohns
➜  vault  python retrieve.py --name JimmyJohns
Key:
Really Fast
➜  vault  cat .JimmyJohns 
1HHF5TPl0cklDU/TXjMQ8nFeqK4zULQ50dVpJ+apgzQ=%                                                                                                                                                                                                                                 ➜  vault

Clone Vault on github

Enjoy !
Jason Riedel

Introducing Vault Read More »

Runner Features Have Been Updated !

Runner Reminder

Runner is a command line tool for running commands on thousands of devices that support SSH. I wrote Runner and use it every single day, because unlike Ansible, Runner truly has no dependencies on the client or server side other than SSH. I have used Runner to build entire datacenters, so it is proven and tested and has a lot of well thought out features, which brings me to todays post. Since I initially debuted Runner I have added a lot of features, but I had yet to check them into github, until now. Here is a run down of Runner’s features.

Features

  • Runner takes your login credentials & doesn’t require you to setup SSH keys on the client machines/devices.
  • Runner can be used through a bastion/jump host via an SSH tunnel (see prunner.py)
  • Runner reads it’s main host list from a file ~/.runner/hosts/hosts-all
  • Runner can accept custom hosts lists via -f
  • -e can be used to echo a command before it is run, this is useful for running commands on F5 load balancers for example, when no output is returned on success.
  • -T will allow you to tune the number of threads, but be careful you can easily exhaust your system or site resources (I.E. do NOT DOS your LDAP authentication servers by trying to do hundreds of threads across thousands of machines, unless you know they can handle it 😉 ).
  • -s is for sudo for those users who have permissions in the sudoers file.
  • -1 reduces any host list down to one host per pool. It uses a regex, which you will likely have to modify for your own host / device naming standard.
  • -r can be used to supply a regular expression for matching hosts. Remember sometimes you have to quote the regex and/or escape the shell when using certain characters.
  • -c will run a single command on many hosts, but -cf will run a series of commands listed in a file on any hosts specified. This is particularly useful for automations. For example, I used it to build out load balancer virtuals and pools on an F5.
  • -p enables you to break apart the number of hosts to run at a time using a percentage. This is a handy & more humanized way to ensure you do not kill your machine or the infrastructure you are managing when you crank threads through the roof 😉

Now that I have taken the time to explain some of those cool features, here’s an example of what it looks like in action.

Runner Demo

Host List

➜  ~  runner -l -r tuxlabs                               
tuxlabs.com
old.tuxlabs.com

There were 2 hosts listed.
➜

Basic Run Using Only -c, -u and defaults

Note: User defaults to the user you are logged in as if you don’t specify -u . Since I am logged in as ‘jriedel’ I have specified the user tuxninja instead.

➜  ~  runner -r tuxlabs -c 'id' -u tuxninja
RUNNER [INFO]: MATCHING HOSTNAMES WITH 'tuxlabs'
RUNNER [INFO]: 2 HOSTS HAVE BEEN SELECTED
RUNNER [INFO]: LOGFILE SET - /Users/jriedel/.runner/logs/runner.log.2015-08-25.01:59:59
RUNNER [INFO]: USER SET - tuxninja
RUNNER [INFO]: SSH CONNECT TIMEOUT is: 10 seconds
RUNNER [INFO]: THREADS SET - 20
RUNNER [INPUT]: Please Enter Site Pass: 
tuxlabs.com: uid=1000(tuxninja) gid=1000(tuxninja) groups=1000(tuxninja),27(sudo)
old.tuxlabs.com: uid=1000(tuxninja) gid=1000(tuxninja) groups=1000(tuxninja),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),114(sambashare),1001(admin)

RUNNER [RESULT]: Successfully logged into 2/2 hosts and ran your command(s) in 0:00:03 second(s)
RUNNER [RESULT]: There were 0 login failures.


RUNNER [INFO]: Your logfile can be viewed @ /Users/jriedel/.runner/logs/runner.log.2015-08-25.01:59:59
➜  ~

The Same Run Using Sudo 

Note: I just realized if you do not prompt for a password for sudo it will fail, I will have to fix that ! Whoops ! P.S. You should always prompt for a password when using sudo !

➜  ~  runner -r tuxlabs -c 'id' -u tuxninja -s
RUNNER [INFO]: MATCHING HOSTNAMES WITH 'tuxlabs'
RUNNER [INFO]: 2 HOSTS HAVE BEEN SELECTED
RUNNER [INFO]: LOGFILE SET - /Users/jriedel/.runner/logs/runner.log.2015-08-25.02:10:27
RUNNER [INFO]: USER SET - tuxninja
RUNNER [INFO]: SSH CONNECT TIMEOUT is: 10 seconds
RUNNER [INFO]: THREADS SET - 20
RUNNER [INFO]: SUDO IS ON
RUNNER [INPUT]: Please Enter Site Pass: 
tuxlabs.com: uid=0(root) gid=0(root) groups=0(root)
old.tuxlabs.com: uid=0(root) gid=0(root) groups=0(root)

RUNNER [RESULT]: Successfully logged into 2/2 hosts and ran your command(s) in 0:00:03 second(s)
RUNNER [RESULT]: There were 0 login failures.


RUNNER [INFO]: Your logfile can be viewed @ /Users/jriedel/.runner/logs/runner.log.2015-08-25.02:10:27
➜  ~

Runner with a command file in super quiet mode  !

➜  ~  cat lets-run-these 
uptime
who
date
uptime -s
➜  ~  

➜  ~  runner -r tuxlabs -cf lets-run-these -T 2 -p 50 -qq -u tuxninja
RUNNER [INPUT]: Please Enter Site Pass: 
tuxlabs.com:  05:17:51 up 14 days,  4:45,  0 users,  load average: 0.00, 0.01, 0.05
old.tuxlabs.com:  03:17:52 up 80 days, 47 min,  1 user,  load average: 0.42, 0.69, 0.78
old.tuxlabs.com: root     pts/0        2015-08-25 02:23 (173.224.162.99)
tuxlabs.com: Tue Aug 25 05:17:52 EDT 2015
old.tuxlabs.com: Tue Aug 25 03:17:53 CST 2015
tuxlabs.com: 2015-08-11 00:32:18
old.tuxlabs.com: 2015-06-06 02:30:42
➜  ~

Example of a simple regex & a failure

➜  ~  runner -r old.* -l
zsh: no matches found: old.*
➜  ~  

➜  ~  runner -r 'old.*' -l
old.tuxlabs.com

There was 1 host listed.
➜  ~

I hope you enjoyed the overview and new features. You can clone Runner on github.

Enjoy,
Jason Riedel

Runner Features Have Been Updated ! Read More »

Object-Oriented Programming With Python : Encapsulation (1/3)

Justification For Learning OOP

linux-python-logo1Since 1995, I have written some form of code, but over the years my career has never taken shape with a primary focus on development. Instead in my various roles of Systems, Network, Application and Datacenter engineering & architecture, I have found excuses to let the inner code hacker in me, out. Allowing me to consistently pursue my passion for coding and automation within the scope of my daily duties. However, this approach has never allowed me to work on a development team and thus the necessity for using object oriented programming rarely has occurred.

Sure I’ve written classes and modules for re-use, but I have never had to place a tremendous amount of forethought into the design for flexibility or inflexibility of the interfaces those classes provide because I was the only one using them. This hasn’t change, but as of late, I find myself realizing my career may be ready for a change. It is likely the next step for me in my career is a full blown software development role. This is partly because of boredom and mastery in my existing field after decades of experience, but mostly because of my own career planning and the apparent industry trends.

Simply put more jobs are moving to software development, and Systems Engineering is on a steady decline due to the advent of Cloud computing, Containers and more. Due to the amazing products, platforms and tools that are now available less and less Systems Engineers are required and I would say Systems Engineers that don’t code are already obsolete, whether they realize it yet or not.

In todays world if you are or are going to be a developer, knowing how to write object oriented code is a requirement and more importantly thinking ahead about who and how your code will be used becomes paramount when designing effective software. This article is intended to help you get a better understanding of how to write object oriented programming using Python.

Procedural Programming vs. Object Oriented Programming

Procedural programming  is a more antiquated paradigm for software design that can be described as:

  • Code that processes data
  • The data we process is stored in variables
  • Then we create functions to process the data in those variables

In the object oriented programming paradigm:

  • We organize data into Objects
  • Functions become Methods
  • And The design of these objects & methods is specified in a Class, which is essentially a blue print.

Object oriented programming is the primary software design paradigm in existence today because it provides programmers with a way to effectively organize and share code for re-use while to protecting the integrity of the existing code. To understand how this works we need to jump right into it with The Three Pillars of Object Oriented Programming.

The Three Pillars (Encapsulation, Inheritance, and Polymorphism)

Encapsulation

Encapsulation is about ensuring the safe storage of data as attributes in an instance.

Encapsulation tells us that :

  • Data should only be accessed through instance methods.
  • Data should always be correct based on the validation requirement set in the class methods.
  • And Data should be safe from changes by external processes.

Great so what does that mean 🙂 It means we should be using ‘setter’ and ‘getter’ methods to access object attribute values. Here’s an example of a class that uses a setter and getter method (note the name setter & getter is not actually required) to set and get the variable/attribute value.

#!/usr/bin/env python

class Tuxlabs(object):
    def setter(self, website):
        self.website = website

    def getter(self):
        return self.website


tuxlabs = Tuxlabs()

tuxlabs.setter('http://www.tuxlabs.com')
print (tuxlabs.getter())

tuxlabs.setter('http://www.google.com')
print (tuxlabs.getter())

The output of this code is: 

➜  tuxlabs  python example.py 
http://www.tuxlabs.com
http://www.google.com
➜  tuxlabs

It’s important to recognize that encapsulation is not enforced by Python. So a programmer using a class is not required to access the data through the getter and setter methods. For example, in the class above someone could set website, without ever interacting with the defined setter and getter classes. This is called breaking encapsulation, and it’s bad form / practice for a programmer to this because the class author & maintainer can no longer validate the data that is being accessed and this can cause unforeseen problems with a program that is dependent on the class it is inheriting from. Here’s a modified example where we are breaking encapsulation. 

#!/usr/bin/env python

class Tuxlabs(object):
    def setter(self, website):
        if 'http' in website:
            self.website = website
        else:
            print 'ERROR: Unable to set website to %s.\nRequired format is: http://www.example.com' % (website)

    def getter(self):
        output = 'Website is set to: ' + str(self.website) + '\n'
        return output

tuxlabs = Tuxlabs()

website = 'http://www.tuxlabs.com'
print "Attempting to set website to: \"%s\"" % (website)
tuxlabs.setter(website)
print (tuxlabs.getter())

website = 'http://www.google.com'
print "Attempting to set website to: \"%s\"" % (website)
tuxlabs.setter(website)
print (tuxlabs.getter())

website = 'I should not be accessing website in the class directly!, but since I am breaking encapsulation it does still work, it\'s just naughty!'
print "Attempting to set website to: \"%s\"" % (website)
tuxlabs.website = website
print tuxlabs.website ## Printing without the getter doh !

print ""
website = 'This is not a website, so an error is thrown!'
print "Attempting to set website to: \"%s\"" % (website)
tuxlabs.setter(website)

Here is the output of the above example: 

➜ tuxlabs python example.py
Attempting to set website to: "http://www.tuxlabs.com"
Website is set to: http://www.tuxlabs.com

Attempting to set website to: "http://www.google.com"
Website is set to: http://www.google.com

Attempting to set website to: "I should not be accessing website in the class directly!, but since I am breaking encapsulation it does still work, it's just naughty!"
I should not be accessing website in the class directly!, but since I am breaking encapsulation it does still work, it's just naughty!

Attempting to set website to: "This is not a website, so an error is thrown!"
ERROR: Unable to set website to This is not a website, so an error is thrown!.
Required format is: http://www.example.com
➜ tuxlabs

A number of things have changed.

  1. We added a variable website to make the example more clear and easy to follow.
  2. We added validation to our setter() method, it now checks to make sure ‘http’ is contained in the value that we are setting for website.
  3. If ‘http’ is not in website the setter() method will throw an error and will not set website!
  4. We added some additional formatting to our getter() method so we can tell when it is being used verses when encapsulation is being broken. getter() now pre-pends any website passed with ‘Website is now set to:’

So let’s walk thru how these changes effected the program and what actually happened. First, we tried to set website to ‘http://www.tuxlabs.com’ and then we changed it to ‘http://www.google.com’. In both of these examples we followed the rules of encapsulation, setting and getting the attribute value through methods in the class. These examples are correct and set website to the value passed and outputed them with the correct formatting we implemented in getter().

Next, we tried setting website to a really long string, without using setter() ! So we did tuxlabs.website = website directly on the instance of our class ! We also circumvented using getter() and just printed in exactly the same, broken way print tuxlabs.website. Unfortunately, as previously mentioned nothing requires the programmer to use our setter and getter methods directly, and thus website is not being checked for containing ‘http’ here and so it can printed our very long string (“I should not be accessing website in the class directly!, but since I am breaking encapsulation it does still work, it\’s just naughty!”).

The last and final example, is an example of encapsulations value proposition. We try to set website to something that does not contain ‘http’ and therefore is not a website. An error is thrown and website is not set, which is exactly what we want.

Encapsulation is  simple, easy to follow and powerful when your programming on or with a team of developers that are going to share code amongst each other. In these scenarios encapsulation is obviously a must promoting collaboration through protecting programmers from potentially mis-using each others code. It should be easy to see now that breaking encapsulation is bad and very poor practice because code that perfectly functions one day, could be broken the next without any changes from you, because you are violating the contract that encapsulation methods of the class provide.

This concludes our learning about encapsulation. Still to come, Inheritance, Polymorphism, and some real world examples!

Until next time…Keep learning,
Jason Riedel

Object-Oriented Programming With Python : Encapsulation (1/3) Read More »

Upgrading to Python 2.7 on CentOS 6.5

Hey Folks,

The systems running Tuxlabs are currently running CentOS 6.5 to emulate a production RHEL like setup for an Openstack Cloud. Running an operating system this old has it’s drawbacks such as dependencies. I was recently installing a well know Python framework and ran into compatibility issues. The framework required Python 2.7 and CentOS 6.5 comes with 2.6. The below is a step by step procedure for how to upgrade to Python 2.7 on CentOS 6.5 if  you ever should need it. However, as a reminder run a newer OS when possible and for god sakes if you don’t need Redhat support, run Ubuntu.

Step one, we verify we are indeed running Python 2.6

[tuxninja@diamond ~]$ python --version
Python 2.6.6
[tuxninja@diamond ~]$

Ok then, let’s upgrade Python to 2.7. First let’s update all of our system applications, just in case for version dependencies and it’s good for security etc.

[tuxninja@diamond ~]$ yum -y update

Next, we have to install Develop Tools, it is a required dependency to install Python.

[tuxninja@diamond ~]$ yum groupinstall "Development tools"

Additionally, we will need these…

[tuxninja@diamond ~]$ sudo yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel

Now, let’s install Python 2.7

[tuxninja@diamond ~]$ cd /opt
[tuxninja@diamond opt]$ sudo wget --no-check-certificate https://www.python.org/ftp/python/2.7.6/Python-2.7.6.tar.xz
[tuxninja@diamond opt]$ sudo tar xf Python-2.7.6.tar.xz 
[tuxninja@diamond opt]$ cd Python-2.7.6
[tuxninja@diamond Python-2.7.6]$ sudo ./configure --prefix=/usr/local
[tuxninja@diamond Python-2.7.6]$ sudo make && sudo make altinstall

It is important to use ‘altinstall’ otherwise you will end up with two different versions of Python on your filesystem, both named ‘python’.

You can verify the install like so

[tuxninja@diamond Python-2.7.6]$ ls -la /usr/local/bin/python2.7*
-rwxr-xr-x 1 root root 6214493 Apr 30 15:14 /usr/local/bin/python2.7
-rwxr-xr-x 1 root root    1674 Apr 30 15:14 /usr/local/bin/python2.7-config
[tuxninja@diamond Python-2.7.6]$ /usr/local/bin/python2.7 --version
Python 2.7.6
[tuxninja@diamond Python-2.7.6]$

That’s it ! Enjoy.

Upgrading to Python 2.7 on CentOS 6.5 Read More »