Exception tracebacks

When an exception is raised but not handled (see Section 4.1.3 of the book), Python will issue a traceback report indicating where in the program flow it occured. This is particularly useful when an error occurs within nested functions or within imported modules. For example, consider the following short program:

import math

def func(x):
    def trig(x):
        for f in (math.sin, math.cos, math.tan):
            print('{f}({x}) = {res}'.format(f=f.__name__, x=x, res=f(x)))
    def invtrig(x):
        for f in (math.asin, math.acos, math.atan):
            print('{f}({x}) = {res}'.format(f=f.__name__, x=x, res=f(x)))
    trig(x)
    invtrig(x)

func(1.2)

The function func passes its argument, x, to its two nested functions. The first, trig, is unproblematic but the second, invtrig, is expected to fail for x out of the domain (range of acceptable values) for the inverse trigonometric function, asin:

sin(1.2) = 0.9320390859672263
cos(1.2) = 0.3623577544766736
tan(1.2) = 2.5721516221263183

Traceback (most recent call last):
  File "exception-test.py", line 14, in <module>
    func(1.2)
  File "exception-test.py", line 12, in func
    invtrig(x)
  File "exception-test.py", line 10, in invtrig
    print('{f}({x}) = {res}'.format(f=f.__name__, x=x, res=f(x)))
ValueError: math domain error

Following the traceback backwards shows that the ValueError exception was raised within invtrig (line 10) which was called from within func (line 12), which was itself called by the exception-test.py module (i.e. program) at line 14.

Note also in this program that f.__name__ is used to return a string representation of a function's name: for example, math.sin.__name__ is 'sin'.