Programming Python on OS/2

Stefan Schwarzer
2-4 Nov 2001
Warpstock Europe 2001

Abstract

From the Python Language Website:

Python is an interpreted, interactive, object-oriented programming language. It is often compared to Tcl, Perl, Scheme or Java.

Python combines remarkable power with very clear syntax. It has modules, classes, exceptions, very high level dynamic data types, and dynamic typing. There are interfaces to many system calls and libraries, as well as to various windowing systems (X11, Motif, Tk, Mac, MFC). New built-in modules are easily written in C or C++. Python is also usable as an extension language for applications that need a programmable interface.

The Python implementation is portable: it runs on many brands of UNIX, on Windows, DOS, OS/2, Mac, Amiga... If your favorite system isn't listed here, it may still be supported, if there's a C compiler for it. Ask around on comp.lang.python -- or just try compiling Python yourself.

Python is copyrighted but freely usable and distributable, even for commercial use.

Overview

Introduction

Origin

Python (named after the comedy group "Monty Python") was invented by Guido van Rossum in the early nineties. His goal was to create a programming language which is easy to learn and to read, and nevertheless powerful.

Strengths of Python

  • easy to install (OS/2 WarpIN package)
  • easy to learn
  • easy to read ("executable pseudocode") and to maintain
  • easy to write
  • well suited to prototyping
  • highly scalable

License

Python is Open Source Software. It may be

  • used and distributed
  • in unmodified or modified form
  • in open or closed source software
  • without having to pay license fees.

Applications

  • text processing (including XML)
  • system administration (mostly on Unix)
  • system integration ("glue language")
  • internet programming (HTML, HTTP, FTP, SMTP, CGI, etc.)
  • numerics (NumPy, with C extensions)
  • image processing (Python Image Library, PIL, with C extensions)

Resources

Links

Books

  • A well-written book on Python is "Learning Python" by Mark Lutz and David Ascher, published by O'Reilly. Unfortunately, the book covers only Python 1.5.2 instead of the current version 2.1 [meanwhile 2.2.1]. On the other hand, most or all examples will also work with Python 2.1 [2.2.1].
  • Mark Lutz also wrote "Programming Python". This book deals with Python applications, mainly text processing, internet programming, and GUI programming. (The GUI stuff requires the Python GUI framework Tkinter and thus won't run with the Presentation Manager but perhaps with XFree/2.) The book's examples are up to Python 2.0.
  • More books are listed on the "Python Bookstore" page.

Data Types

There are three groups of data types in Python:

  • Scalars have the subtypes integer, long integer (with an arbitrary number of digits), floating point numbers, complex numbers, and strings.
        i = 1; li = 9999999999L; f = 3.14; c = 3+4j; s = 'Hello'
    
    There is no explicit pointer type.
  • Sequences contain any number of arbitrary objects in a defined order. Sequence types are subdivided into lists and tuples. Lists are mutable, i. e. can be changed in-place while tuples cannot.
        L = [1, 3];  L.append(7);  print L[2]
    
    prints 7, while
        T = (1, 3);  T.append(7)
    
    results in an error message. Tuples can't be modified after creation. However, you can build a new tuple from existing ones:
        T = (1, 3) + (7,)
    
  • Associative lists (more commonly known as dictionaries) allow the access to values based on keys. These keys can be arbitrary but immutable objects. For example,
        D = {'b': 'Python', 'a': 5};  print D['a']
    
    prints 5.
  • Unlike Pascal, C, C++ or Java, Python is a dynamically typed language. Thus, the following code is perfectly valid Python:
        a = 7                       # 7 (integer)
        a = a / 2.0                 # 3.5 (float)
        a = str(2*a) + ' bytes'     # '7 bytes' (string)
    

Operators

Python has the following operators:

  • Arithmetic and bitwise operators
        + - * / % **  ~ << >> & ^ |
    
  • Relational and logical operators
        is in < <= > >= == != not and or
    
  • Assignments
        = += -= *= /= %= **= <<= >>= &= ^= |=
    
  • Other operators
        () [] {} [:] `` . lambda
    

Compound Statements

  • Statements that belong to the same logical group are indented by the same amount of whitespace:
        if a > 0:
            b = 1
            c = 2
    
    Usually, each statement starts on a new line. You can write several statements on the same line if you delimit them by semicolons (like in the section "Data types").
  • You don't need special characters (like "{" and "}" in C) to mark a group of statements; the logical structure is determined by the indentation.
  • A statement is continued by putting a backslash \ at the end of a line. This isn't necessary if there are still parentheses (or brackets or braces) open:
        my_list = [1,           # open bracket, statement continues
                   ['abc', 2],  # nested list
                   -3+6j]       # closed outermost bracket, statement ends
        print my_list
    

Conditional Execution

  • Python uses if, elif (not elsif or elseif), and else to denote conditional execution of statements. For example,
        if a > b:
            print 'a is greater than b.'
        elif a < b:
            print 'a is lower than b.'
        else:
            print 'a equals b.'
    
    Note the colons and the identation.
  • You can use "abbreviated" interval tests:
        if 2 <= a <= 7:
            print 'a is in the interval [2, 7].'
    

Loops

  • Loops in Python are defined by the keywords for and while.
  • The following example uses a while loop to collect all numbers from 0 to 99 in a list.
        numbers = []
        i = 0
        while i < 100:
            numbers.append(i)
            i = i + 1   # or  i += 1  since Python 2.0
    
  • A similar for loop looks like
        numbers = []
        for i in range(100):
            numbers.append(i)
    
  • Instead of the expicit loops above also an implicit loop is possible:
        numbers = range(100)
    
    range(100) generates a list of all integers from 0 to 99 (not 100).
  • You can use a for loop to iterate not only over numbers but also over arbitrary sequences:
        for programming_language in [C, Perl, Python, Pascal]:
            explain(programming_language)
    
  • break quits the (next innermost) loop immediately:
        found = 0
        for entry in entries:
            if searched == entry:
                found = 1
                break   # don't iterate further if the
                        # searched entry has been found
    
  • continue starts the next iteration of the next innermost loop:
        # squares of the positive numbers in a list
        X = [1, -1, 2.4, -5.7]
        for num in X:
            if num <= 0:
                continue
            print 'number:', num, '  square:', num**2
    
    prints
        number: 1   square: 1
        number: 2.3   square: 5.76
    

Application Example

A file is read, sorted, and written to a file with the additional extension .sorted. You could do it with this - rather long - solution:

    import sys

    # get filename
    filename = sys.argv[1]      # script name in sys.argv[0]
    lines = []

    # read file
    try:
        file = open(filename, 'r')
        while 1:
            line = file.readline()
            if line == '':
                break
            lines.append(line)  # lines + [line]
        file.close()
    except IOError, msg:
        print filename, "is not readable (%s)" % msg
        sys.exit(1)

    # sort
    lines.sort()
    filename = filename + '.sorted'

    # write file
    try:
        file = open(filename, 'w')
        for line in lines:
            file.write(line)
        file.close()
    except IOError, msg:
        print filename, "is not writable (%s)" % msg

You might do it shorter:

    import sys

    # get filename
    filename = sys.argv[1]

    # read file
    try:
        file = open(filename, 'r')
        lines = file.readlines()
        file.close()
    except IOError, msg:
        print filename, "is not readable (%s)" % msg
        sys.exit(1)

    # sort lines
    lines.sort()
    filename = filename + '.sorted'

    # write file
    try:
        file = open(filename, 'w')
        file.writelines(lines)
        file.close()
    except IOError, msg:
        print filename, "is not writable (%s)" % msg
If you don't want to catch errors explicitly, you could even code this (quick and dirty ;-) ) solution:
    from sys import argv

    lines = open(argv[1], 'r').readlines()
    lines.sort()
    open(argv[1]+'.sorted', 'w').writelines(lines)
Note: If an error occurs, this example will fail with a traceback, not silently.

Subroutines

  • You can use the keywords def or lambda to define Python subroutines. These are more commonly known as functions.
  • In the definition of a function with def, the body of the function is indented.
  • Arguments are passed as named variables.
  • Any Python object (e. g. a list, a dictionary, or a list of tuples of class objects) can be returned to the caller via the keyword return.
  • If there is no return statement or no value is given the special value None is returned.
  • Default arguments (as in C++) are possible.
  • The order of the parameters in the call may be changed if if you assign them to the appropriate names which appear the function's argument list.
  • The following function returns the index of an item if it is found in the sequence, or None otherwise.
        def index(searched, items):
            "Look for 'searched' in the sequence 'items'"
            for i in range( len(items) ):
                if items[i] == searched:
                    return i
            return None                         # not found, statement
                                                # written for clarity
    
        print index( 3, [1, 2, 3, 4] )          # search 3 in the list
        print index( items=[1, 2, 3, 4],        # alternative syntax
                     searched=3 )
    

Modules

Basics

  • Modules are programming units in individual files. This separation is mainly done to make the code in the module reusable in other contexts.
  • To make a module usable in many contexts, it has to designed explicitly for this purpose.
  • Besides the interpreter and documentation, the Python distribution contains a large number of modules (about 200). For example, there are modules for text processing and interfaces to internet protocols (HTTP, FTP, etc.).
  • Module files have the suffix .py which is the same as for regular Python "programs". So a module file can also be passed to the interpreter on the command line to be executed as a program.
  • There is no special statement that marks a file as a module. The distinction between a module and a program is based on its usage, not on its code.
  • An example for a very simple module is
        # a_module.py
    
        an_integer = 1
        a_list = [2, 3]
    
        def square(x):
            return x**2
    
  • In other files the module is loaded and thus made available via the import statement.
  • Names which are defined in the imported module are prefixed with the module's name and a dot, e. g.
        # main program
    
        import a_module
    
        test = a_module.an_integer  # test = 1
        test = a_module.square(7)   # test = 49
    

Commonly Used Python Modules

  • The sys and os modules are used for basic interactions with the operating system.
        import sys
        import os
        print sys.argv[1:]      # print command line arguments
        os.system('dir')        # show an OS/2 directory
    
  • math deals with certain mathematical functions.
        import math
        print math.sin(1.0)     # 0.841470984808
    
  • re works with regular expressions.
        import re
        pattern = re.compile(r'[A-Za-z]+')
        text = 'Fri 26 June 2001, 26Jun2001'
        print pattern.findall(text)   # ['Fri', 'June', 'Jun']
    
  • The time module contains date and time related functions.
        import time
        # print the currect date in the format 2001-11-02
        print time.strftime( '%Y-%m-%d', time.localtime() )
    

Object-oriented Programming (OOP)

Basics of OOP

  • Objects provide variables (state) and functions (methods) which work on these variables. As an example, consider an oven which is described by the variables
    • temperature (in °C)
    • flap open/closed
    and has the functions
    • open_flap (no parameters)
    • close_flap (no parameters)
    • fill_with (parameter: material)
    • heat_to (parameter: desired temperature in °C)
    • cool_down (no parameters)
  • There can exist several objects (instances) of the same kind which are independent of each other. For example, there could be many ovens with their individual state.
  • The interface between the object and the code that uses it should only reveal what is done by the object but not how it is accomplished internally. The latter remains private to the object.
  • Object types (classes) can form a basis for similar but specialized types. The derivation of new classes from existing ones is called inheritance.

    In the context of the above example, you could define a new class CirculationAirOven which is a special kind of an oven. This new class could contain a new state variable which represents if the circulation is on or off, and an additional method to change this state.

OOP in Python

  • A new class is generated with the class statement (see below).
  • The constructor, named __init__, builds a new object. During that, the object can be initialized, i. e. state variables can be set and methods can be called.
  • A call of a method implicitly passes a reference to the object as the first argument.
  • To derive a new class from an existing one the old class is specified as a "parameter" in the class statement that defines the new class.
  • A possible implementation of the mentioned oven class is
        # oven.py
    
        class Oven:
            def __init__(self):
                self.temperature = 20       # room temperature
                self.is_open = 0            # flap closed
                self.material = None        # oven is empty
    
            def open_flap(self):
                if self.temperature > 20:
                    print "Please close the flap before opening the oven."
                    return
                self.is_open = 1
    
            def close_flap(self):
                self.is_open = 0
    
            def fill_with(self, material):
                if not self.is_open:
                    print "Please open the oven before attempting to fill it."
                    return
                self.material = material
    
            def heat_to(self, temperature):
                if self.is_open:
                    print "Please close the flap before heating up the oven."
                    return
                self.temperature = temperature
    
            def cool_down(self):
                self.temperature = 20
    
    
        # ----------------------------------------------------------------
        # circulating_air_oven.py
    
        import oven
    
        class CirculationAirOven(oven.Oven):
            def __init__(self):
                oven.Oven.__init__(self)
                self.circulation = 0
    
            def circulation_on(self):
                self.circulation = 1
    
            def circulation_off(self):
                self.circulation = 0
    
    
        # ----------------------------------------------------------------
        # oventest.py
    
        import circulating_air_oven, time
    
        oven = circulating_air_oven.CirculationAirOven()
        oven.open_flap()
        oven.fill_with('dough')
        oven.close_flap()
        oven.circulation_on()
        oven.heat_to(250)
        time.sleep(60*60)           # bake one hour
        oven.cool_down()
        oven.circulation_off()
    

More Examples

  • get an HTML page from a server and print it
        import urllib
        page = urllib.urlopen('http://www.ndh.net/home/sschwarzer/python/')
        print page.read()
        page.close()
    
  • compose and send an email
        import smtplib
        mailhost = smtplib.SMTP('mail.ndh.net')
        text = """From: s.schwarzer@ndh.net
        To: s.schwarzer@ndh.net
        Subject: Demo mail
    
        This is a small demo text."""
        mailhost.sendmail('s.schwarzer@ndh.net', [s.schwarzer@ndh.net'], text)
        mailhost.quit()
    
  • work with comples numbers (output is shown in bold)
        import math, cmath
        print math.sin(1.0)
        0.841470984808
        print math.sin(1+3j)
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        TypeError: can't convert complex to float; use e.g. abs(z)
        print cmath.sin(1+3j)
        (8.4716454543+5.41268092318j)
    

Summary

  • Think before you act. This even applies to Python. ;-)
  • Also, in Python, you are able to write code that is hard to understand, if you are careless.
  • The time you save in Python by implementation details (debugging!) can be invested in better program design and algorithms.

URL of this page: http://www.sschwarzer.net/python/warpstock_europe_2001.html