Part I, Getting Started

% python
...copyright information lines...
>>> "Hello World!"
'Hello World!'
>>>                     # Ctrl-D or Ctrl-Z to exit, or window close



# module1.py
print 'Hello module world!'

% python module1.py
Hello module world!



% python
>>> import module1
Hello module world!
>>>



#!/usr/local/bin/python          (or #!/usr/bin/env python)
print 'Hello module world!'

% chmod +x module1.py

% module1.py
Hello module world!



% python
>>> 1 / 0
Traceback (innermost last):
  File "<stdin>", line 1, in ?
ZeroDivisionError: integer division or modulo
>>>
>>> x
Traceback (innermost last):
  File "<stdin>", line 1, in ?
NameError: x



L = [1, 2]
L.append(L)






Part II, Types and Operations

Numbers

>>> 2 ** 16              # 2 raised to the power 16
65536
>>> 2 / 5, 2 / 5.0       # Integer / truncates, float / doesn't
(0, 0.40000000000000002)

Strings

>>> "spam" + "eggs"      # Concatenation
'spameggs'
>>> S = "ham"
>>> "eggs " + S
'eggs ham'
>>> S * 5                # Repetition
'hamhamhamhamham'
>>> S[:0]                # An empty slice at the front--[0:0]
''
>>> "green %s and %s" % ("eggs", S)  # Formatting
'green eggs and ham'

Tuples

>>> ('x',)[0]                        # Indexing a single-item tuple
'x'
>>> ('x', 'y')[1]                    # Indexing a 2-item tuple
'y'

Lists

>>> L = [1,2,3] + [4,5,6]            # List operations
>>> L, L[:], L[:0], L[-2], L[-2:]
([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [], 5, [5, 6])
>>> ([1,2,3]+[4,5,6])[2:4]
[3, 4]
>>> [L[2], L[3]]                       # Fetch from offsets; store in a list
[3, 4]
>>> L.reverse(); L                   # Method: reverse list in-place
[6, 5, 4, 3, 2, 1]
>>> L.sort(); L                      # Method: sort list in-place
[1, 2, 3, 4, 5, 6]
>>> L.index(4)                         # Method: offset of first 4 (search)
3

Dictionaries

>>> {'a':1, 'b':2}['b']              # Index a dictionary by key.
2
>>> D = {'x':1, 'y':2, 'z':3}
>>> D['w'] = 0                       # Create a new entry.
>>> D['x'] + D['w']
1
>>> D[(1,2,3)] = 4                   # A tuple used as a key (immutable)
>>> D
{'w': 0, 'z': 3, 'y': 2, (1, 2, 3): 4, 'x': 1}
>>> D.keys(), D.values(), D.has_key((1,2,3))          # Methods
(['w', 'z', 'y', (1, 2, 3), 'x'], [0, 3, 2, 4, 1], 1)

Empties

>>> [[]], ["",[],(),{},None]         # Lots of nothings: empty objects
([[]], ['', [], (), {}, None])



>>> L = [1, 2, 3, 4]
>>> L[4]
Traceback (innermost last):
  File "<stdin>", line 1, in ?
IndexError: list index out of range
>>> L[-1000:100]
[1, 2, 3, 4]
>>> L[3:1]
[]
>>> L
[1, 2, 3, 4]
>>> L[3:1] = ['?']
>>> L
[1, 2, 3, '?', 4]



>>> L = [1,2,3,4]
>>> L[2] = []
>>> L
[1, 2, [], 4]
>>> L[2:3] = []
>>> L
[1, 2, 4]
>>> del L[0]
>>> L
[2, 4]
>>> del L[1:]
>>> L
[2]
>>> L[1:2] = 1
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: illegal argument type for built-in operation



>>> X = 'spam'
>>> Y = 'eggs'
>>> X, Y = Y, X
>>> X
'eggs'
>>> Y
'spam'



>>> D = {}
>>> D[1] = 'a'
>>> D[2] = 'b'
>>> D[(1, 2, 3)] = 'c'
>>> D
{1: 'a', 2: 'b', (1, 2, 3): 'c'}



>>> D = {'a':1, 'b':2, 'c':3}
>>> D['a']
1
>>> D['d']
Traceback (innermost last):
  File "<stdin>", line 1, in ?
KeyError: d
>>> D['d'] = 4
>>> D
{'b': 2, 'd': 4, 'a': 1, 'c': 3}
>>>
>>> L = [0, 1]
>>> L[2]
Traceback (innermost last):
  File "<stdin>", line 1, in ?
IndexError: list index out of range
>>> L[2] = 3
Traceback (innermost last):
  File "<stdin>", line 1, in ?
IndexError: list assignment index out of range



>>> "x" + 1
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: illegal argument type for built-in operation
>>>
>>> {} + {}
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: bad operand type(s) for +
>>>
>>> [].append(9)
>>> "".append('s')
Traceback (innermost last):
  File "<stdin>", line 1, in ?
AttributeError: attribute-less object
>>>
>>> {}.keys()
[]
>>> [].keys()
Traceback (innermost last):
  File "<stdin>", line 1, in ?
AttributeError: keys
>>>
>>> [][:]
[]
>>> ""[:]
''



>>> S = "spam"
>>> S[0][0][0][0][0]
's'
>>> L = ['s', 'p']
>>> L[0][0][0]
's'



>>> S = "spam"
>>> S = S[0] + 'l' + S[2:]
>>> S
'slam'
>>> S = S[0] + 'l' + S[2] + S[3]
>>> S
'slam'



>>> me = {'name':('mark', 'e', 'lutz'), 'age':'?', 'job':'engineer'}
>>> me['job']
'engineer'
>>> me['name'][2]
'lutz'



# File: maker.py
file = open('myfile.txt', 'w')
file.write('Hello file world!\n')        # Or: open().write()
file.close()                             # close not always needed

# File: reader.py
file = open('myfile.txt')                # 'r' is default open mode
print file.read()                        # Or print open().read()

% python maker.py
% python reader.py
Hello file world!

% ls -l myfile.txt
-rwxrwxrwa   1 0        0             19 Apr 13 16:33 myfile.txt



>>> [].__methods__
['append', 'count', 'index', 'insert', 'remove', 'reverse', 'sort',...]
>>> dir([])
['append', 'count', 'index', 'insert', 'remove', 'reverse', 'sort',...]






Part III, Statements and Syntax

>>> S = 'spam'
>>> for c in S:
...     print ord(c)
...
115
112
97
109

>>> x = 0
>>> for c in S: x += ord(c)           # Or: x = x + ord(c)
...
>>> x
433

>>> x = []
>>> for c in S: x.append(ord(c))
...
>>> x
[115, 112, 97, 109]

>>> map(ord, S)
[115, 112, 97, 109]



>>> D = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6, 'g':7}
>>> D
{'f': 6, 'c': 3, 'a': 1, 'g': 7, 'e': 5, 'd': 4, 'b': 2}
>>>
>>> keys = D.keys()
>>> keys.sort()
>>> for key in keys:
...     print key, '=>', D[key]
...
a => 1
b => 2
c => 3
d => 4
e => 5
f => 6
g => 7

>>> for key in sorted(D):           # in more recent Pythons
...     print key, '=>', D[key]



L = [1, 2, 4, 8, 16, 32, 64]
X = 5

i = 0
while i < len(L):
    if 2 ** X == L[i]:
        print 'at index', i
        break
    i = i+1
else:
    print X, 'not found'
        

L = [1, 2, 4, 8, 16, 32, 64]
X = 5

for p in L:
    if (2 ** X) == p:
        print (2 ** X), 'was found at', L.index(p)
        break
else:
    print X, 'not found'


L = [1, 2, 4, 8, 16, 32, 64]
X = 5

if (2 ** X) in L:
    print (2 ** X), 'was found at', L.index(2 ** X)
else:
    print X, 'not found'
        

X = 5
L = []
for i in range(7): L.append(2 ** i)
print L

if (2 ** X) in L:
    print (2 ** X), 'was found at', L.index(2 ** X)
else:
    print X, 'not found'
        

X = 5
L = map(lambda x: 2**x, range(7))
print L

if (2 ** X) in L:
    print (2 ** X), 'was found at', L.index(2 ** X)
else:
    print X, 'not found'






Part IV, Functions

% python
>>> def func(x): print x
...
>>> func("spam")
spam
>>> func(42)
42
>>> func([1, 2, 3])
[1, 2, 3]
>>> func({'food': 'spam'})
{'food': 'spam'}



# mod.py

def adder(x, y):
    return x + y

print adder(2, 3)
print adder('spam', 'eggs')
print adder(['a', 'b'], ['c', 'd'])

% python mod.py
5
spameggs
['a', 'b', 'c', 'd']



# adders.py

def adder1(*args):
    print 'adder1',
    if type(args[0]) == type(0):    # Integer?
         sum = 0                    # Init to zero.
    else:                           # else sequence:
         sum = args[0][:0]          # Use empty slice of arg1.
    for arg in args:
        sum = sum + arg
    return sum

def adder2(*args):
    print 'adder2',
    sum = args[0]               # Init to arg1.
    for next in args[1:]:
        sum += next             # Add items 2..N.
    return sum

for func in (adder1, adder2):
    print func(2, 3, 4)
    print func('spam', 'eggs', 'toast')
    print func(['a', 'b'], ['c', 'd'], ['e', 'f'])

% python adders.py
adder1 9
adder1 spameggstoast
adder1 ['a', 'b', 'c', 'd', 'e', 'f']
adder2 9
adder2 spameggstoast
adder2 ['a', 'b', 'c', 'd', 'e', 'f']



# mod.py

def adder(good=1, bad=2, ugly=3):
    return good + bad + ugly

print adder()
print adder(5)
print adder(5, 6)
print adder(5, 6, 7)
print adder(ugly=7, good=6, bad=5)

% python mod.py
6
10
14
18
18



# dicts.py

def copyDict(old):
    new = {}
    for key in old.keys():
        new[key] = old[key]
    return new

def addDict(d1, d2):
    new = {}
    for key in d1.keys():
        new[key] = d1[key]
    for key in d2.keys():
        new[key] = d2[key]
    return new

% python
>>> from dicts import *
>>> d = {1: 1, 2: 2}
>>> e = copyDict(d)
>>> d[2] = '?'
>>> d
{1: 1, 2: '?'}
>>> e
{1: 1, 2: 2}

>>> x = {1: 1}
>>> y = {2: 2}
>>> z = addDict(x, y)
>>> z
{1: 1, 2: 2}



def f1(a, b): print a, b             # Normal args

def f2(a, *b): print a, b            # Positional varargs

def f3(a, **b): print a, b           # Keyword varargs

def f4(a, *b, **c): print a, b, c    # Mixed modes

def f5(a, b=2, c=3): print a, b, c   # Defaults

def f6(a, b=2, *c): print a, b, c    # Defaults and positional varargs


% python
>>> f1(1, 2)                  # Matched by position (order matters)
1 2
>>> f1(b=2, a=1)              # Matched by name (order doesn't matter)
1 2

>>> f2(1, 2, 3)               # Extra positionals collected in a tuple
1 (2, 3)

>>> f3(1, x=2, y=3)           # Extra keywords collected in a dictionary
1 {'x': 2, 'y': 3}

>>> f4(1, 2, 3, x=2, y=3)     # Extra of both kinds
1 (2, 3) {'x': 2, 'y': 3}

>>> f5(1)                     # Both defaults kick in.
1 2 3
>>> f5(1, 4)                  # Only one default used
1 4 3

>>> f6(1)                     # One argument: matches "a"
1 2 ()
>>> f6(1, 3, 4)               # Extra positional collected
1 3 (4,)



8.	\
# primes.py

#from __future__ import division

def prime(y):
    if y <= 1:                              # For some y > 1
        print y, 'not prime'
    else:
        x = y // 2                          # Future / fails
        while x > 1:
            if y % x == 0:                  # No remainder?
                print y, 'has factor', x
                break                       # Skip else.
            x -= 1
        else:
            print y, 'is prime'

prime(13); prime(13.0)
prime(15); prime(15.0)
prime(3);  prime(2)
prime(1);  prime(-3)


% python primes.py
13 is prime
13.0 is prime
15 has factor 5
15.0 has factor 5.0
3 is prime
2 is prime
1 not prime
-3 not prime


def timer(reps, func, *args):
    import time
    start = time.clock()
    for i in xrange(reps):
        apply(func, args)
    return time.clock()  start



>>> values = [2, 4, 9, 16, 25]
>>> import math

>>> res = []
>>> for x in values: res.append(math.sqrt(x))
...
>>> res
[1.4142135623730951, 2.0, 3.0, 4.0, 5.0]

>>> map(math.sqrt, values)
[1.4142135623730951, 2.0, 3.0, 4.0, 5.0]

>>> [math.sqrt(x) for x in values]
[1.4142135623730951, 2.0, 3.0, 4.0, 5.0]






Part V, Modules

# mymod.py

def countLines(name):
    file = open(name)
    return len(file.readlines())

def countChars(name):
    return len(open(name).read())

def test(name):                                  # Or pass file object
    return countLines(name), countChars(name)    # Or return a dictionary

% python
>>> import mymod
>>> mymod.test('mymod.py')
(10, 291)



def countLines(name):
    tot = 0
    for line in open(name): tot += 1
    return tot

def countChars(name):
    tot = 0
    for line in open(name): tot += len(line)
    return tot



# mymod2.py

def countLines(file):
    file.seek(0)                      # Rewind to start of file.
    return len(file.readlines())

def countChars(file): 
    file.seek(0)                      # Ditto (rewind if needed)
    return len(file.read())

def test(name):
    file = open(name)                            # Pass file object.
    return countLines(file), countChars(file)    # Open file only once.

>>> import mymod2
>>> mymod2.test("mymod2.py")
(11, 392)



% python
>>> from mymod import *
>>> countChars("mymod.py")
291



# mymod.py

def countLines(name):
    file = open(name)
    return len(file.readlines())

def countChars(name):
    return len(open(name).read())

def test(name):                                  # Or pass file object
    return countLines(name), countChars(name)    # Or return a dictionary

if __name__ == '__main__':
    print test('mymod.py')

% python mymod.py
(13, 346)



# myclient.py

from mymod import countLines, countChars
print countLines('mymod.py'), countChars('mymod.py')

% python myclient.py
13 346



import myclient
myclient.countLines(...)

from myclient import countChars
countChars(...)



import myclient
myclient.mymod.countLines(...)

from myclient import mymod
mymod.countChars(...)



# File: mod1.py
somename = 42

# File: collector.py
from mod1 import *       # Collect lots of names here.
from mod2 import *       # from assigns to my names.
from mod3 import *

>>> from collector import somename



C:\python25> mkdir mypkg
C:\Python25> move mymod.py mypkg\mymod.py
C:\Python25> edit mypkg\__init__.py
...coded a print statement...

C:\Python25> python
>> import mypkg.mymod
initializing mypkg
>>> mypkg.mymod.countLines('mypkg\mymod.py')
13
>>> from mypkg.mymod import countChars
>>> countChars('mypkg\mymod.py')
346






Part VI, Classes and OOP

# adder.py

class Adder:
    def add(self, x, y):
        print 'not implemented!'
    def __init__(self, start=[]):
        self.data = start
    def __add__(self, other):                # Or in subclasses?
        return self.add(self.data, other)    # Or return type?

class ListAdder(Adder):
    def add(self, x, y):
        return x + y

class DictAdder(Adder):
    def add(self, x, y):
        new = {}
        for k in x.keys(): new[k] = x[k]
        for k in y.keys(): new[k] = y[k]
        return new

% python
>>> from adder import *
>>> x = Adder()
>>> x.add(1, 2)
not implemented!
>>> x = ListAdder()
>>> x.add([1], [2])
[1, 2]
>>> x = DictAdder()
>>> x.add({1:1}, {2:2})
{1: 1, 2: 2}

>>> x = Adder([1])
>>> x + [2]
not implemented!
>>>
>>> x = ListAdder([1])
>>> x + [2]
[1, 2]
>>> [2] + x
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: __add__ nor __radd__ defined for these operands



# adder2.py

class Adder:
    def __init__(self, start=[]):
        self.data = start
    def __add__(self, other):            # Pass a single argument.
        return self.add(other)           # The left side is in self.
    def add(self, y):
        print 'not implemented!'

class ListAdder(Adder):
    def add(self, y):
        return self.data + y

class DictAdder(Adder):
    def add(self, y):
        pass  # Change me to use self.data instead of x.

x = ListAdder([1, 2 ,3])
y = x + [4, 5, 6]
print y               # Prints [1, 2, 3, 4, 5, 6]



# mylist.py

class MyList:
    def __init__(self, start):
        #self.wrapped = start[:]           # Copy start: no side effects
        self.wrapped = []                  # Make sure it's a list here.
        for x in start: self.wrapped.append(x)
    def __add__(self, other):
        return MyList(self.wrapped + other)
    def __mul__(self, time):
        return MyList(self.wrapped * time)
    def __getitem__(self, offset):
        return self.wrapped[offset]
    def __len__(self):
        return len(self.wrapped)
    def __getslice__(self, low, high):
        return MyList(self.wrapped[low:high])
    def append(self, node):
        self.wrapped.append(node)
    def __getattr__(self, name):       # Other members: sort/reverse/etc
        return getattr(self.wrapped, name)
    def __repr__(self):
        return repr(self.wrapped)

if __name__ == '__main__':
    x = MyList('spam')
    print x
    print x[2]
    print x[1:]
    print x + ['eggs']
    print x * 3
    x.append('a')
    x.sort()
    for c in x: print c,

% python mylist.py
['s', 'p', 'a', 'm']
a
['p', 'a', 'm']
['s', 'p', 'a', 'm', 'eggs']
['s', 'p', 'a', 'm', 's', 'p', 'a', 'm', 's', 'p', 'a', 'm']
a a m p s



# mysub.py

from mylist import MyList

class MyListSub(MyList):
    calls = 0                                 # Shared by instances

    def __init__(self, start):
        self.adds = 0                         # Varies in each instance
        MyList.__init__(self, start)

    def __add__(self, other):
        MyListSub.calls = MyListSub.calls + 1   # Class-wide counter
        self.adds = self.adds + 1               # Per instance counts
        return MyList.__add__(self, other)

    def stats(self):
        return self.calls, self.adds                  # All adds, my adds

if __name__ == '__main__':
    x = MyListSub('spam')
    y = MyListSub('foo')
    print x[2]
    print x[1:]
    print x + ['eggs']
    print x + ['toast']
    print y + ['bar']
    print x.stats()

% python mysub.py
a
['p', 'a', 'm']
['s', 'p', 'a', 'm', 'eggs']
['s', 'p', 'a', 'm', 'toast']
['f', 'o', 'o', 'bar']
(3, 2)



>>> class Meta:
...     def __getattr__(self, name):        
...         print 'get', name
...     def __setattr__(self, name, value):
...         print 'set', name, value
...
>>> x = Meta()
>>> x.append
get append
>>> x.spam = "pork"
set spam pork
>>>
>>> x + 2
get __coerce__
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: call of non-function
>>>
>>> x[1]
get __getitem__
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: call of non-function

>>> x[1:5]
get __len__
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: call of non-function



% python
>>> from setwrapper import Set
>>> x = Set([1, 2, 3, 4])       # Runs __init__
>>> y = Set([3, 4, 5])

>>> x & y                       # __and__, intersect, then __repr__
Set:[3, 4]
>>> x | y                       # __or__, union, then __repr__
Set:[1, 2, 3, 4, 5]

>>> z = Set("hello")            # __init__ removes duplicates.
>>> z[0], z[-1]                 # __getitem__ 
('h', 'o')

>>> for c in z: print c,        # __getitem__ 
...
h e l o
>>> len(z), z                   # __len__, __repr__
(4, Set:['h', 'e', 'l', 'o'])

>>> z & "mello", z | "mello"
(Set:['e', 'l', 'o'], Set:['h', 'e', 'l', 'o', 'm'])



# multiset.py

from setwrapper import Set

class MultiSet(Set):
    """
    inherits all Set names, but extends intersect
    and union to support multiple operands; note
    that "self" is still the first argument (stored
    in the *args argument now); also note that the
    inherited & and | operators call the new methods
    here with 2 arguments, but processing more than 
    2 requires a method call, not an expression:
    """

    def intersect(self, *others):
        res = []
        for x in self:                     # Scan first sequence
            for other in others:           # for all other args.
                if x not in other: break   # Item in each one?
            else:                          # No: break out of loop
                res.append(x)              # Yes: add item to end
        return Set(res)

    def union(*args):                      # self is args[0].
        res = []
        for seq in args:                   # For all args
            for x in seq:                  # For all nodes
                if not x in res:
                    res.append(x)          # Add new items to result.
        return Set(res)



>>> from multiset import *
>>> x = MultiSet([1,2,3,4])
>>> y = MultiSet([3,4,5])
>>> z = MultiSet([0,1,2])

>>> x & y, x | y                               # Two operands
(Set:[3, 4], Set:[1, 2, 3, 4, 5])

>>> x.intersect(y, z)                          # Three operands
Set:[]
>>> x.union(y, z)
Set:[1, 2, 3, 4, 5, 0]

>>> x.intersect([1,2,3], [2,3,4], [1,2,3])     # Four operands 
Set:[2, 3]
>>> x.union(range(10))                         # non-MultiSets work too.
Set:[1, 2, 3, 4, 0, 5, 6, 7, 8, 9]



class Lister:
    def __repr__(self):
        return ("<Instance of %s(%s), address %s:\n%s>" %
                          (self.__class__.__name__,   # My class's name
                           self.supers(),              # My class's supers
                           id(self),                     # My address
                           self.attrnames()) )         # name=value list
    def attrnames(self):
        ...unchanged...
    def supers(self):
        result = ""
        first = 1
        for super in self.__class__.__bases__:   # One level up from class
            if not first:
                result = result + ", "
            first = 0
            result = result + super.__name__      # name, not repr(super) 
        return result

C:\python\examples> python testmixin.py
<Instance of Sub(Super, Lister), address 7841200:
        name data3=42
        name data2=eggs
        name data1=spam
>



# lunch.py

class Lunch:
    def __init__(self):             # Make/embed Customer and Employee.
        self.cust = Customer()
        self.empl = Employee()
    def order(self, foodName):      # Start a Customer order simulation.
        self.cust.placeOrder(foodName, self.empl)
    def result(self):               # Ask the Customer about its Food.
        self.cust.printFood()

class Customer:
    def __init__(self):                        # Initialize my food to None.
        self.food = None
    def placeOrder(self, foodName, employee):  # Place order with Employee.
        self.food = employee.takeOrder(foodName)
    def printFood(self):                       # Print the name of my food.
        print self.food.name

class Employee:
    def takeOrder(self, foodName):    # Return a Food, with requested name.
        return Food(foodName)

class Food:
    def __init__(self, name):         # Store food name.
        self.name = name

if __name__ == '__main__':
    x = Lunch()                         # Self-test code
    x.order('burritos')                 # If run, not imported
    x.result()
    x.order('pizza')
    x.result()

% python lunch.py
burritos
pizza



# zoo.py

class Animal:
    def reply(self):   self.speak()          # Back to subclass
    def speak(self):   print 'spam'          # Custom message

class Mammal(Animal):
    def speak(self):   print 'huh?'

class Cat(Mammal):
    def speak(self):   print 'meow'

class Dog(Mammal):
    def speak(self):   print 'bark'

class Primate(Mammal):
    def speak(self):   print 'Hello world!'

class Hacker(Primate): pass                  # Inherit from Primate.



# parrot.py

class Actor:
    def line(self): print self.name + ':', repr(self.says())

class Customer(Actor):
    name = 'customer'
    def says(self): return "that's one ex-bird!"

class Clerk(Actor):
    name = 'clerk'
    def says(self): return "no it isn't..."

class Parrot(Actor):
    name = 'parrot'
    def says(self): return None

class Scene:
    def __init__(self):
        self.clerk    = Clerk()       # Embed some instances.
        self.customer = Customer()    # Scene is a composite.
        self.subject  = Parrot()

    def action(self):
        self.customer.line()          # Delegate to embedded.
        self.clerk.line()
        self.subject.line()






Part VII, Exceptions and Tools

# oops.py

def oops():
    raise IndexError

def doomed():
    try:
        oops()
    except IndexError:
        print 'caught an index error!'
    else:
        print 'no error caught...'

if __name__ == '__main__': doomed()

% python oops.py
caught an index error!



# oops.py

MyError = 'hello'

def oops():
    raise MyError, 'world'

def doomed():
    try:
        oops()
    except IndexError:
        print 'caught an index error!'
    except MyError, data:
        print 'caught error:', MyError, data
    else:
        print 'no error caught...'

if __name__ == '__main__':
    doomed()

% python oops.py
caught error: hello world



# oop_oops.py

class MyError: pass

def oops():
    raise MyError()

...rest unchanged...



% python oop_oops.py
caught error: __main__.MyError <__main__.MyError instance at 0x00867550>



# safe2.py

import sys, traceback

def safe(entry, *args):
    try:
        apply(entry, args)                 # catch everything else
    except:
        traceback.print_exc()
        print 'Got', sys.exc_type, sys.exc_value

import oops
safe(oops.oops)

% python safe2.py
Traceback (innermost last):
  File "safe2.py", line 5, in safe
    apply(entry, args)                     # catch everything else
  File "oops.py", line 4, in oops
    raise MyError, 'world'
hello: world
Got hello world



# safe2_new.py

def safe(entry, *args):
    try:
        entry(*args)                 # catch everything else
    except:
        traceback.print_exc()
        print 'Got', sys.exc_info(){0], sys.exc_info()[1]




# bigdir.py: Find the largest file in a single directory

dirname = r'C:\Python25\Lib'
import os, glob

allsizes = []
allpy = glob.glob(os.path.join(dirname, '*.py'))
for filename in allpy:
    filesize = os.path.getsize(filename)
    allsizes.append((filesize, filename))

allsizes.sort()
print allsizes[:2]
print allsizes[-2:] 




# bigtree.py: Find the largest file in an entire directory tree

import sys
if sys.platform[:3] == 'win':
    dirname = r'C:\Python25\Lib'
else:
    dirname = '/usr/lib/python'
import os, glob

allsizes = []
for (thisDir, subsHere, filesHere) in os.walk(dirname):
    for filename in filesHere:
        if filename.endswith('.py'):
            fullname = os.path.join(thisDir, filename)
            fullsize = os.path.getsize(fullname)
            allsizes.append((fullsize, fullname))

allsizes.sort()
print allsizes[:2]
print allsizes[-2:]




# bigmod.py: Find largest Python source file on the module import search path

import sys, os, pprint
visited  = {}
allsizes = []
for srcdir in sys.path:
    for (thisDir, subsHere, filesHere) in os.walk(srcdir):
        thisDir = os.path.normpath(thisDir)
        if thisDir.upper() in visited:
            continue
        else:
            visited[thisDir.upper()] = True
        for filename in filesHere:
            if filename.endswith('.py'):
                pypath  = os.path.join(thisDir, filename)
                try:
                    pysize = os.path.getsize(pypath)
                except:
                    print 'skipping', pypath
                allsizes.append((pysize, pypath))
                
allsizes.sort()
pprint.pprint(allsizes[:3])
pprint.pprint(allsizes[-3:])




# summer1.py: sum columns in a text file separated by commas

filename = 'data.txt'
sums = {}

for line in open(filename):
    cols = line.split(',')
    nums = [int(col) for col in cols]
    for (ix, num) in enumerate(nums):
        sums[ix] = sums.get(ix, 0) + num
        
for key in sorted(sums):
    print key, '=', sums[key]




# summer2.py: similar to prior, but using lists instead of dictionaries for sums

import sys
filename = sys.argv[1]
numcols  = int(sys.argv[2])
totals   = [0] * numcols

for line in open(filename):
    cols = line.split(',')
    nums = [int(x) for x in cols]
    totals = [(x + y) for (x, y) in zip(totals, nums)]
        
print totals
 



# regtest.py: Test for regressions in the output of a set of scripts

import os
testscripts = [dict(script='test1.py', args=''),
               dict(script='test2.py', args='spam')]

for testcase in testscripts:
    commandline = '%(script)s %(args)s' % testcase
    output = os.popen(commandline).read()
    result = testcase['script'] + '.result'
    if not os.path.exists(result):
        open(result, 'w').write(output)
        print 'Created:', result
    else:
        priorresult = open(result).read()
        if output != priorresult:
            print 'FAILED:', testcase['script']
            print output
        else:
            print 'Passed:', testcase['script'] 




# gui1.py: Build a GUI with Tkinter with buttons that change color and grow 

from Tkinter import *
import random
fontsize = 25
colors = ['red', 'green', 'blue', 'yellow', 'orange', 'white', 'cyan', 'purple']

def reply(text):
    print text
    popup = Toplevel()
    color = random.choice(colors)
    Label(popup, text='Popup', bg='black', fg=color).pack()
    L.config(fg=color)

def timer():
    L.config(fg=random.choice(colors))
    win.after(250, timer)
  
def grow():
    global fontsize
    fontsize += 5
    L.config(font=('arial', fontsize, 'italic'))
    win.after(100, grow)
  
win = Tk()
L = Label(win, text='Spam',
          font=('arial', fontsize, 'italic'), fg='yellow', bg='navy', relief=RAISED)
L.pack(side=TOP, expand=YES, fill=BOTH)
Button(win, text='press', command=(lambda: reply('red'))).pack(side=BOTTOM, fill=X)
Button(win, text='timer', command=timer).pack(side=BOTTOM, fill=X)
Button(win, text='grow' , command=grow).pack(side=BOTTOM, fill=X)
win.mainloop()




# gui2.py: Similar to prior, but use classes so each window has own state information 

from Tkinter import *
import random

class MyGui:
    """
    A GUI with buttons that change color and make the label grow
    """
    colors = ['blue', 'green', 'orange', 'red', 'brown', 'yellow']
    
    def __init__(self, parent, title='popup'):
        parent.title(title)
        self.growing = False
        self.fontsize = 10
        self.lab = Label(parent, text='Gui1', fg='white', bg='navy')
        self.lab.pack(expand=YES, fill=BOTH)
        Button(parent, text='Spam', command=self.reply).pack(side=LEFT)
        Button(parent, text='Grow', command=self.grow).pack(side=LEFT)
        Button(parent, text='Stop', command=self.stop).pack(side=LEFT)

    def reply(self):
        "change the button's color at random on Spam presses"
        self.fontsize += 5
        color = random.choice(self.colors)
        self.lab.config(bg=color,
                font=('courier', self.fontsize, 'bold italic'))

    def grow(self):
        "start making the label grow on Grow presses"
        self.growing = True
        self.grower()
        
    def grower(self):
        if self.growing:
            self.fontsize += 5
            self.lab.config(font=('courier', self.fontsize, 'bold'))
            self.lab.after(500, self.grower)
            
    def stop(self):
        "stop the button growing on Stop presses"
        self.growing = False

class MySubGui(MyGui):
    colors = ['black', 'purple']      # customize to change color choices
    
MyGui(Tk(), 'main')
MyGui(Toplevel())
MySubGui(Toplevel())
mainloop() 




# mailscan.py: email inbox scanning and maintenance utility

"""
scan pop email box, fetching just headers, allowing
deletions without downloading the complete message
"""

import poplib, getpass, sys

mailserver = 'your pop email server name here'                 # pop.rmi.net
mailuser   = 'your pop email user name here'                   # brian
mailpasswd = getpass.getpass('Password for %s?' % mailserver)

print 'Connecting...'
server = poplib.POP3(mailserver)
server.user(mailuser)                      
server.pass_(mailpasswd)                   

try:
    print server.getwelcome()
    msgCount, mboxSize = server.stat()
    print 'There are', msgCount, 'mail messages, size ', mboxSize
    msginfo = server.list()
    print msginfo
    for i in range(msgCount):
        msgnum  = i+1
        msgsize = msginfo[1][i].split()[1]
        resp, hdrlines, octets = server.top(msgnum, 0)         # get hdrs only
        print '-'*80
        print '[%d: octets=%d, size=%s]' % (msgnum, octets, msgsize) 
        for line in hdrlines: print line

        if raw_input('Print?') in ['y', 'Y']:
            for line in server.retr(msgnum)[1]: print line     # get whole msg
        if raw_input('Delete?') in ['y', 'Y']:
            print 'deleting'
            server.dele(msgnum)                                # delete on srvr
        else:
            print 'skipping'
finally: 
    server.quit()                                  # make sure we unlock mbox
raw_input('Bye.')                                  # keep window up on windows




# cgigreet.py: CGI client-side script to interact with a web browser

#!/usr/bin/python
import cgi
form = cgi.FieldStorage()                # parse form data
print "Content-type: text/html\n"        # hdr plus blank line
print "<HTML>"
print "<title>Reply Page</title>"        # html reply page
print "<BODY>"
if not form.has_key('user'):
    print "<h1>Who are you?</h1>"
else:
    print "<h1>Hello <i>%s</i>!</h1>" % cgi.escape(form['user'].value)
print "</BODY></HTML>"




# makesqldb.py: Database script to populate and query a MySql database

from MySQLdb import Connect
conn = Connect(host='localhost', user='root', passwd='darling')
curs = conn.cursor()
try:
    curs.execute('drop database testpeopledb')
except:
    pass  # did not exist

curs.execute('create database testpeopledb')
curs.execute('use testpeopledb')
curs.execute('create table people (name char(30), job char(10), pay int(4))')

curs.execute('insert people values (%s, %s, %s)', ('Bob', 'dev', 50000))
curs.execute('insert people values (%s, %s, %s)', ('Sue', 'dev', 60000))
curs.execute('insert people values (%s, %s, %s)', ('Ann', 'mgr', 40000))

curs.execute('select * from people')
for row in curs.fetchall():
	print row

curs.execute('select * from people where name = %s', ('Bob',))
print curs.description
colnames = [desc[0] for desc in curs.description]
while True:
    print '-' * 30
    row = curs.fetchone()
    if not row: break
    for (name, value) in zip(colnames, row):
        print '%s => %s' % (name, value)

conn.commit()   # save inserted records




# makedb.py: Database script to populate a shelve with Python objects

rec1 = {'name': {'first': 'Bob', 'last': 'Smith'},
        'job':  ['dev', 'mgr'],
        'age':  40.5}

rec2 = {'name': {'first': 'Sue', 'last': 'Jones'},
        'job':  ['mgr'],
        'age':  35.0}

import shelve
db = shelve.open('dbfile')
db['bob'] = rec1
db['sue'] = rec2
db.close()




# updatedb.py: Database script to print and update shelve created in prior script

import shelve
db = shelve.open('dbfile')
for key in db:
    print key, '=>', db[key]

bob = db['bob']
bob['age'] += 1
db['bob'] = bob
db.close()


