Invalid code raises exceptions:
In [1]:
42/0
Formerly, the try and except statements were used to handle exceptions, but you can also create your own exceptions with raise.
In [2]:
raise Exception('This is the error message.')
In [12]:
def boxPrint(symbol, width, height):
"""
A program to build boxes like this:
***************
* *
* *
***************
"""
# print top part
print(symbol * width)
# print the sides (excluding top and bottom)
for i in range(height-2):
# empty spaces in the middle except the last two spots
print(symbol + (' ' * (width - 2) + symbol))
# print the bottom
print(symbol * width)
# Working functions
boxPrint('*', 15,5)
boxPrint('O', 10,8)
# Not working
boxPrint('**', 5,16)
To handle situations with the wrong input, an exception can be raised:
In [23]:
def boxPrint(symbol, width, height):
"""
A program to build boxes like this:
***************
* *
* *
***************
"""
# Exception statements
if len(symbol) != 1:
raise Exception('"symbol" needs to be a string of length 1.')
if (width < 2) or (height <2):
raise Exception('"width" and "height" must be greater than or equal to 2.')
print(symbol * width)
for i in range(height-2):
print(symbol + (' ' * (width - 2) + symbol))
print(symbol * width)
# Working functions
boxPrint('*', 10,5)
boxPrint('O', 12,8)
In [20]:
# Exception statement 1
boxPrint('**', 5,16)
In [19]:
# Exception statement 2
boxPrint('*', 1,1)
Exceptions have a particular structure, defined as the traceback or call stack.
The traceback shows exactly what function the error occured in, here boxPrint(**,5,16) and boxPrint(*,1,1). It also shows where the exception was define in the program, lines 14 and 16.
The traceback module contains some tools to deal with the traceback, including returning it as a string value.
This is useful for storing code in a log so it doesnt break the entire function on error.
In [28]:
import traceback
import os
# Sample code to raise exception and store code in a log
try:
# Raise this exception
raise Exception('This is the error message.\n')
except:
# Open/create a log in append mode
errorFile = open(os.path.abspath('files/error_log.txt'), 'a')
errorFile.write(traceback.format_exc())
errorFile.close()
print('The traceback info was written to error_log.txt')
In [29]:
# Open the error file and read the log; will increase for every error
errorFile = open(os.path.abspath('files/error_log.txt'), 'r')
errorFile.read()
Out[29]:
An assertion is a sanity check to make sure the code isn't doing something obviously wrong. It is another kind of exception.
If an assert statement evaluates to false, then an error is raised.
In [30]:
assert False, 'This is the error message.'
In [33]:
market_2nd = {'ns':'green', 'ew':'red'} #ns: north south, ew: east west
def switchLights(intersection):
for key in intersection.keys():
if intersection[key] == 'green':
intersection[key] = 'yellow'
elif intersection[key] == 'yellow':
intersection[key] = 'red'
elif intersection[key] == 'red':
intersection[key] = 'green'
print(market_2nd)
switchLights(market_2nd) # Run function in data structure
print(market_2nd)
This code is buggy, because the 'north-south' direction is green, while the 'east-west' direction is yellow. The cars crash into each other at intersections.
We need to create a sanity check with an assert statement to make sure illogical things throw errors.
In [34]:
market_2nd = {'ns':'green', 'ew':'red'} #ns: north south, ew: east west
def switchLights(intersection):
for key in intersection.keys():
if intersection[key] == 'green':
intersection[key] = 'yellow'
elif intersection[key] == 'yellow':
intersection[key] = 'red'
elif intersection[key] == 'red':
intersection[key] = 'green'
# if false, raise assert statement
assert 'red' in intersection.values(), 'Neither light is red at ' + str(intersection) + '!'
print(market_2nd)
switchLights(market_2nd) # Run function in data structure
print(market_2nd)
An assert statement asserts that a condition holds True. If the assert is False, then it raises an assert statement.
This improves the ability to debug, by holding the program to logical output.
Assertions should be used for programmer errors (invalid outputs, wrong returns, etc.) They are meant to be recovered from.
Exceptions should be used for user errogs (invalid inputs, bugs, etc.) They are meant to stop invalid program use.
Any error statements will help improve the debug flow, and help you find errors sooner instead of later.
raise Exception('Error message').assert condition,'Error message'.