Intro

A friend of mine, who is studying Computer Science, asked me to help him learning a Programming Language. Students with no background in programming often learn Java as first language, which I find very hard to learn, with nearly no experience and knowledge of the concepts used in Java. My understanding of developing computer programs is, one need to learn the basic concepts of developing and with mastering one language, nearly every language can be understood and mastered. I decided to teach him Python, because Python is a widely used and grown Scripting Language, which covers object orientation, mostly clean syntax and readability. Readability is good for learning a language by looking at programs from others.

In several parts I will slowly cover the basics of Python. I don’t like guides, with no real world examples, implementing Fibonacci for the millions time. In the first parts we will build a small tool for monitoring/checking a Website. Later we will program something more complex, like a Web Crawler.

If anyone, from an English speaking country, like to lecture my text, feel free to send me corrections.

Requirements

  • Basic knowledge of programming, I will not describe what a variable is for
  • Linux, preferable based on Debian, like Ubuntu
  • Working Python installation, >= Python 2.7, < Python 3.0

Developer Environment

To write Python programs I use a combination of tools, which make life more easy.

Editor

I use Sublime Text. It’s fast and light. There are tons of great plugins, written in Python. It can be tested for free, without registration, as long as you need to. The editor is Cross-platform, available for Linux, Mac OS X and Windows. I recommend using the plugins Package Control, which is for installing plugins easily and SublimeLint, installable via Package Control. SublimeLint checks your Python code (and more) for syntax and style guides. My basic settings for Sublime Text (Preferences -> Settings User) are the following.

{
    "detect_indentation": false,
    "draw_white_space": "all",
    "find_selected_text": true,
    "fold_buttons": false,
    "font_options":
    [
        "subpixel_antialias"
    ],
    "font_size": 14,
    "highlight_line": true,
    "ignored_packages":
    [
        "Vintage"
    ],
    "rulers":
    [
        72,
        79
    ],
    "tab_size": 4,
    "translate_tabs_to_spaces": true,
    "trim_trailing_white_space_on_save": true,
    "use_tab_stops": true
}

VirtualEnv

VirtualENV is a fantastic Python tool to isolate dedicated environments from the system. It creates an environment that has its own installation directories, that doesn’t share libraries with other VirtualENV environments and by default even not with the Python system installation. Inside a VirtualENV you can do no harm. Install as much Packages as you like, screw around, if something broke, delete the VirtualENV and create a fresh one.

Installation

cd ~/Downloads/
wget -O pypa-virtualenv.tar.gz https://github.com/pypa/virtualenv/tarball/master
tar xf pypa-virtualenv.tar.gz
cd pypa-virtualenv-*/
sudo python setup.py install

Create your first VirtualENV and activate it

virtualenv myenv
cd myenv
source bin/activate

Now you are inside a VirtualENV. Leave the VirtualENV with the deactivate command. In a VirtualENV one has access to several programs. Of course, the Python interpreter python. Also pip. PIP is a Python Package Manager, which can manage packages from the Python Package Index, PyPI. PIP will be used later.

Hello World

Our first program will be the famous “Hello World” program.

#! python

if __name__ == '__main__':
    print 'Hello World!'

Create a VirtualENV, active it, open your favorite editor, paste the code from above and execute the created Python file with the Python interpreter, python hello_world.py. The string “Hello World!” will be printed.

  • Line 1: The Shebang, explained here. Must have in each Python script, which will be called with python! Good style and very useful with VirtualENVs.
  • Line 3: I will explain this strange if statement later. For now just accept it, that it is good style to start your main program logic inside this if statement.
  • Line 4: The print statement. print evaluates the given expression (in this case a string) and writes the resulting object to STDOUT (Console).

Very simple, now a little more complex.

#! python

if __name__ == '__main__':
    print '%s %s!' % ('Hello', 'World')

This will also print “Hello World!”, but now we are using string formatting. String formatting is extremely useful. Let me show why.

#! python

if __name__ == '__main__':
    hello = 'Hello'
    world = 'World'
    print '%s %s!' % (hello, world)

In this example the string “Hello” is assigned to the variable hello and “World” assigned to world. String formatting basically means to replace the objects inside the parentheses with the placeholders “%s” in the string. The placeholder (for example “%s”) is called conversion type. A conversion type defines to which data type the passed object will be converted.

myvar = 1
'Foo %s' % (myvar)

myvar assigned to an integer will be converted to a string.

myvar = 1
'Foo %d' % (myvar)

myvar assigned to an integer will be converted to an integer.

myvar = 'string'
'Foo %d' % (myvar)

myvar assigned to a string will be converted to an integer? No! This will cause a TypeError, because Python expects a number.

myvar = 1.1
'Foo %d' % (myvar)

myvar assigned to a float will be converted to an integer? Yes! But this will not print “Foo 1.1”, but “Foo 1” because “%d” is an integer conversion type.

String formatting will not only be used if it comes to printing text. Each time you need to build a string from other objects, or concatenate two string objects, string formatting is useful and good style.

mynumber = 1
myword = 'Hi!'
mystring = str(mynumber) + ' ' + myword
print mystring

Or

mynumber = 1
myword = 'Hi!'
mystring = '%s %s' % (mynumber, myword)
print mystring

Both examples do exactly the same, but the second one is much more readable. And that’s what Python is all about, readability.

mynumber = 1
myword = 'Hi!'
mystring = '%d %s' % (mynumber, myword)
print mystring

Using “%d” instead of “%s” is even better because mynumber is an integer and everything else than integer is unexpected, which we will tell the formatted string by using “%d” instead of “%s”.

Slightly more complex Hello World coming up.

#! python

def hello():
    return 'Hello'

def world():
    return 'World'

if __name__ == '__main__':
    print '%s %s!' % (hello(), world())

This time we used functions to build the “Hello World!” string. The function hello() returns a ‘Hello’ string object and the function world returns a ‘World’ string object. Again we are using string formatting, to format the returned values by both functions into one string. Now, the last “Hello World!”.

#! python

def words_to_string(first_word, second_word):
    return '%s %s' % (first_word, second_word)

if __name__ == '__main__':
    print words_to_string('Hello', 'World!')

Functions are introduced by the def keyword. Inside the parentheses you can define the function arguments, or leave them empty, if no arguments should be passed to the function. Isn’t it called “Method”? No, outside classes functions are called functions. Inside classes functions are called methods. The words_to_string function needs two arguments, which will be used to build a new string. The new string will be returned by the function.

Indentation

Python does not use curly braces “{}” to define a block of code. Blocks are defined by indentation. Each time you begin a new block of code after a compound statement like if, for, while, def, class, …, you need to indent the block by one level.

def words_to_string(first_word, second_word):
    return '%s %s' % (first_word, second_word)

or

if __name__ == '__main__':
    print 'Hi!'

Common style defined by Python Enhancement Proposal 8 (PEP 8) is to use 4 spaces for each indentation level. Don’t mix tabs and spaces. Unexpected indents will raise an IndentationError.

if __name__ == '__main__':
    print 'Hi!'
        print 'Ho!'
IndentationError: unexpected indent

if statement

if is an control flow statement, meaning you can influence the flow/order of your program. The if statement is introduced by the if keyword and an expression, which evaluates to true or false. If the expression result is true, the if block will be executed, if the result is false, the block will not be executed. To compare objects, the comparison operators can be used.

if 1 + 1 == 2:
    print '1 + 1 = 2'

or

mybool = True
if mybool:
    print 'mybool is True'

or

mybool = False
if not mybool:
    print 'mybool is False'

True and False

There are more objects which evaluate to true or false. Here are some examples.

Data Types True

  • mystring = 'foo': A not empty string is true
  • mybool = True: A bool with value True is of course true
  • mynumber = 1: A positive or negative number, which is not 0, is true
  • mydict = {'key': 'value'}: A not empty dict is true
  • mylist = [1,2,3]: A not empty list is true

Data Types False

  • mystring = '': An empty string is false
  • mybool = False: A bool with value False is of course false
  • mynumber = 0: 0 is false
  • mydict = {}: An empty dict is false
  • mylist = []: An empty list is false

Comparison Operators

Relational Comparison Operators

  • : (a > b) a greater than b

  • < : (a < b) a less than b
  • = : (a <= b) a greater than or equal to b

  • <= : (a <= b) a less than or equal to b
  • == : (a == b) a equal to b
  • != : (a != b) a not equal to b

Identity Comparison Operators

  • is : (a is b) a and b are the same object
  • is not : (a is not b) a and b are not the same object

Boolean Operations

  • and : (a > b) and (a < 1)
  • or : (a > b) or (a == b)
  • not : not a

The strange if statement

As you may noticed the functions are defined outside the if statement. Qoute from a good Stackoverflow answer What does if name == ‘main’ do

When the Python interpreter reads a source file, it executes all of the code found in it. Before executing the code, it will define a few special variables. For example, if the python interpreter is running that module (the source file) as the main program, it sets the special name variable to have a value “main”. If this file is being imported from another module, name will be set to a different value.

[…]

One of the reasons for doing this is that sometimes you write a module (a .py file) where it can be executed directly. Alternatively, it can also be imported and used in another module. By doing the main check, you can have that code only execute when you want to run the module as a program and not have it execute when someone just wants to import your module and call your functions themselves.

The if statement is some kind of protection, which keeps Python from executing code, which should only be executed if the .py File is executed directly.

Import Python Modules

Python libraries are organized in modules. A module is a Python .py file. The name of the module is defined by the name of the .py file. A module “mymodule” would be a .py file called “mymodule.py”. Module names can also be represented by a folder. In this case a folder name is the module name and inside this folder is a .py file called “init.py”, which represent the .py file from which content can be imported. To load content from a module the import statement is used. The contents which can be imported from a module are variables, functions and classes. There are modules already shipped with your Python installation. These modules can be found in the Python Standard Library. User generated modules are shipped via Python Packages. Lots of useful packages can be found on the Python Package Index.

There are two ways to import contents from a module. You can import the namespace of a module, meaning you can access all exported contents of a module under the name of the namespace. The second way is, to import contents from a module directly into the namespace of your Python script.

#! python

import time

if __name__ == '__main__':
    print time.time()

In this case the time module will be imported. All exported contents of time are accessible under the namespace “time”. Here we access the time function from time and print the current time.

#! python

from time import time

if __name__ == '__main__':
    print time()

Here we use the import syntax to directly import a function from the time module into the namespace of the Python script. You can import everything from a module into the script namespace by importing “”, from time import *, but this is bad style. Don’t do it. If you need to import everything from a module, import the module name like import time and access the contents of the module via the namespace time. Importing “” can easily cause name conflicts, which are confusing to debug sometimes.

What you learned by now

  • Print an object
  • Format strings
  • Assign variables
  • Define functions
  • How to indent
  • if statement
  • Comparison Operators
  • Boolean Operations
  • if name == ‘main
  • Import and use modules

Exercise

Instead of just listing all language features of Python we will stop introducing new syntax and start using the learned knowledge for a first program. We will implement a script, which monitors a website.

Requirements

For monitoring a website, we need a HTTP client library. Python has two HTTP clients in its standard library, but they are complicated to use and badly designed. Instead we will use Requests. Requests wraps around the HTTP clients in the Python standard library by providing a really user friendly API. The script should also check for the request time. So we need a module, which provides an interface to the current time. We use the time module for that.

Install requests

To install Requests, we use the pip command. Activate your VirtualENV and enter the following command.

pip install requests

A clean install looks like this:

Downloading/unpacking requests
  Downloading requests-1.1.0.tar.gz (337kB): 337kB downloaded
  Running setup.py egg_info for package requests

Installing collected packages: requests
  Running setup.py install for requests

Successfully installed requests
Cleaning up...

Introduction

HTTP GET with Requests

This is how you execute an HTTP GET request with Requests. Requests will return a Response object.

#! python

import requests

if __name__ == '__main__':
    response = requests.get('http://aboutsimon.com/')

Time a GET request

The Python time module provides a time function, which will return the time in seconds since the epoch (UNIX timestamp) as a floating point number. To time something we need a start time and an end time. Between start and end, we will execute the GET request. Subtract start from end and you will get the elapsed time for the GET request.

#! python

import requests
from time import time

if __name__ == '__main__':
    start_time = time()
    response = requests.get('http://aboutsimon.com/')
    end_time = time()
    elapsed_time = end_time - start_time

    print 'GET request took: %f seconds' % (elapsed_time)

The “%f” in the string stands for float, because elapsed_time is of type float and we like to see the precision of float.

Access attributes from response

The Response object from the GET requests provides a couple of attributes. With response.status_code we can access the HTTP Status Code of the HTTP Server Response as integer. If everything is fine, the Status Code should be 200 for “HTTP OK”. response.content will return the page content we requested as str object, which is a ASCII string. The content itself isn’t that interesting for now, but the size of the content is. To get the size of a string we use the built-in function len. Built-in functions must not be imported, they are just there, like keywords (if, def, import etc).

#! python

import requests
from time import time

if __name__ == '__main__':
    start_time = time()
    response = requests.get('http://aboutsimon.com/')
    end_time = time()
    elapsed_time = end_time - start_time

    print 'GET request took: %f seconds' % (elapsed_time)
    print 'HTTP Status Code: %d' % (response.status_code)
    print 'Page size: %d byte' % (len(response.content))

Your turn

Your exercise is, implement a Python script, which checks a Website.

  • Define a function get_website, with a URL as argument, which executes the GET request and returns the reponse
  • Check if the reponse Status Code is 200, if yes print “HTTP Status Code: OK”, if not print an error message
  • Check if the request took less than 0.5 seconds, if yes print the request time, if not print an error message
  • Check if the response content size is greater than 0 bytes, if yes print the size, if not print an error message
  • Read PEP 8 and check if your script is compliant to PEP 8.

In Part 2 of Python Lessons, I will post a solution, to this exercise.