>>> def fetcher(obj, index):
...     return obj[index]



>>> x = 'spam'
>>> fetcher(x, 3)           # Like x[3]
'm'



>>> fetcher(x, 4)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in fetcher
IndexError: string index out of range



>>> try:
...     fetcher(x, 4)
... except IndexError:
...     print 'got exception'
...
got exception
>>>



>>> def catcher():
...     try:
...         fetcher(x, 4)
...     except IndexError:
...         print 'got exception'
...     print 'continuing'
...
>>> catcher()
got exception
continuing
>>>



>>> bad = 'bad'
>>> try:
...     raise bad
... except bad:
...     print 'got bad'
...
got bad



>>> raise bad
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in ?
    raise bad
bad



>>> class Bad(Exception): pass
...
>>> def doomed(): raise Bad()
...
>>> try:
...     doomed()
... except Bad:
...     print 'got Bad'
...
got Bad
>>>



>>> try:
...     fetcher(x, 3)
... finally:
...     print 'after fetch'
...
'm'
after fetch



fetcher(x, 3)
print 'after fetch'



>>> def after():
...     try:
...         fetcher(x, 4)
...     finally:
...         print 'after fetch'
...     print 'after try?'
...
>>> after()
after fetch
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in after
  File "<stdin>", line 2, in fetcher
IndexError: string index out of range



>>> def after():
...     try:
...         fetcher(x, 3)
...     finally:
...         print 'after fetch'
...     print 'after try?'
...
>>> after()
after fetch
after try?
>>>




try:
    action()
except NameError:
    ... 
except IndexError
    ...
except KeyError:
    ...
except (AttributeError, TypeError, SyntaxError):
    ...
else:
    ...



try:
    action()
except NameError:
    ...                   # Handle NameError.
except IndexError:
    ...                   # Handle IndexError.
except:
    ...                   # Handle all other exceptions.
else:
    ...                   # Handle the no-exception case.



try:
    action()
except:
    ...          # Catch all possible exceptions.



try:
    ...run code...
except IndexError:
    ...handle exception...
# Did we get here because the try failed or not?



try:
    ...run code...
except IndexError:
    ...handle exception...
else:
    ...no exception occurred...



try:
    ...run code...
    ...no exception occurred...
except IndexError:
    ...handle exception...



# bad.py

def gobad(x, y):
    return x / y

def gosouth(x):
    print gobad(x, 0)

gosouth(1)



% python bad.py
Traceback (most recent call last):
  File "bad.py", line 7, in <module>
    gosouth(1)
  File "bad.py", line 5, in gosouth
    print gobad(x, 0)
  File "bad.py", line 2, in gobad
    return x / y
ZeroDivisionError: integer division or modulo by zero



def kaboom(x, y):
    print x + y                    # Trigger TypeError.

try:
    kaboom([0,1,2], "spam")
except TypeError:                  # Catch and recover here.
    print 'Hello world!'
print 'resuming here'              # Continue here if exception or not.



class MyError(Exception): pass

def stuff(file):
    raise MyError()

file = open('data', 'w')     # Open an output file.
try:
    stuff(file)              # Raises exception
finally:
    file.close()             # Always close file to flush output buffers.
...                          # Continue here only if no exception.



try:
    main-action
except Exception1:
    handler1
except Exception2:
    handler2
else:
    else-block
finally:
    finally-block



try:
    try:
        main-action
    except Exception1:
        handler1
    except Exception2:
        handler2
    else:
        no-error
finally:
    clean-up



# mergedexc.py

print '-' * 30, '\nEXCEPTION RAISED AND CAUGHT'
try:
    x = 'spam'[99]
except IndexError:
    print 'except run'
finally:
    print 'finally run'
print 'after run'

print '-' * 30, '\nNO EXCEPTION RAISED'
try:
    x = 'spam'[3]
except IndexError:
    print 'except run'
finally:
    print 'finally run'
print 'after run'

print '-' * 30, '\nNO EXCEPTION RAISED, ELSE RUN'
try:
    x = 'spam'[3]
except IndexError:
    print 'except run'
else:
    print 'else run'
finally:
    print 'finally run'
print 'after run'

print '-' * 30, '\nEXCEPTION RAISED BUT NOT CAUGHT'
try:
    x = 1 / 0
except IndexError:
    print 'except run'
finally:
    print 'finally run'
print 'after run'



------------------------------ 
EXCEPTION RAISED AND CAUGHT
except run
finally run
after run
------------------------------ 
NO EXCEPTION RAISED
finally run
after run
------------------------------ 
NO EXCEPTION RAISED, ELSE RUN
else run
finally run
after run
------------------------------ 
EXCEPTION RAISED BUT NOT CAUGHT
finally run

Traceback (most recent call last):
  File "C:/Python25/mergedexc.py", line 32, in <module>
    x = 1 / 0
ZeroDivisionError: integer division or modulo by zero



class MyBad: pass

def stuff():
    raise MyBad()            # Trigger exception manually.

try:
    stuff()                  # Raises exception
except MyBad:
    print 'got it'           # Handle exception here.
...                          # Resume execution here.



# raisedata.py

myException = 'Error'                 # String object

def raiser1():
    raise myException, "hello"        # Raise, pass data.

def raiser2():
    raise myException                 # Raise, None implied.

def tryer(func):
    try:
        func()
    except myException, extraInfo:    # Run func; catch exception+data.
        print 'got this:', extraInfo



% python
>>> from raisedata import *
>>> tryer(raiser1)                  # Explicitly passed extra data
got this: hello
>>> tryer(raiser2)                  # Extra data is None by default.
got this: None



>>> try:
...     raise IndexError, 'spam'
... except IndexError:
...     print 'propagating'
...     raise
...
propagating
Traceback (most recent call last):
  File "<stdin>", line 2, in ?
IndexError: spam



# asserter.py

def f(x):
    assert x < 0, 'x must be negative'
    return x ** 2

% python
>>> import asserter
>>> asserter.f(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "asserter.py", line 2, in f
    assert x < 0, 'x must be negative'
AssertionError: x must be negative



def reciprocal(x):
    assert x != 0     # a useless assert!
    return 1 / x      # python checks for zero automatically



from __future__ import with_statement

with open(r'C:\python\scripts') as myfile:
    for line in myfile:
        print line
        line = line.resplace('spam', SPAM')
        ...more code here...



lock = threading.Lock()
with lock:
    # critical section of code
    ...access shared resources...



# withas.py

from __future__ import with_statement         # required in Python 2.5

class TraceBlock:
    def message(self, arg):
        print 'running', arg
    def __enter__(self):
        print 'starting with block'
        return self
    def __exit__(self, exc_type, exc_value, exc_tb):
        if exc_type is None:
            print 'exited normally\n'
        else:
            print 'raise an exception!', exc_type
            return False  # propagate
        
with TraceBlock() as action:
    action.message('test 1')
    print 'reached'
    
with TraceBlock() as action:
    action.message('test 2')
    raise TypeError
    print 'not reached'



% python withas.py
starting with block
running test 1
reached
exited normally

starting with block
running test 2
raise an exception! <type 'exceptions.TypeError'>

Traceback (most recent call last):
  File "C:/Python25/withas.py", line 22, in <module>
    raise TypeError
TypeError



doStuff()
{                                    # C program:
     if (doFirstThing() == ERROR)    # Detect errors everywhere
          return ERROR;              # even if not handled here.
     if (doNextThing() == ERROR)
          return ERROR;
     ...
     return doLastThing();
}

main()
{
     if (doStuff() == ERROR)
          badEnding();
     else
          goodEnding();
}



def doStuff():       # Python code
    doFirstThing()   # We don't care about exceptions here,
    doNextThing()    # so we don't need to detect them here.
    ...
    doLastThing()

if__name__ == '__main__':
    try:
        doStuff()    # This is where we care about results,
    except:          # so it's the only place we must check.
        badEnding()
    else:
        goodEnding()
 
