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'
.