Rapid Python Programming

Chapter 5

Exceptions

There is no doubt whatsoever that you have already watched your programs crash. Every time the crash occurs it prints out the all too familiar message Traceback (most recent call last):" followed by your File ’name.py’ a line number and some additional information telling you why the program crashed. The bottom line is that checking for ↓errors is tedious and boring. However, you must master the basics of this section before moving forward in your software development career. Please note that exceptions are not the absolute answer to preventing your programs from crashing. Code can be very complex and some problems just can’t be predicted. Lets see an example and crash a program:

#!/usr/bin/python
#tro.py
x=int(raw_input("Enter a number: "))
print x

Run the program using any letter such as ’a’ and you will get the following

results:

Pay ATTENTION to indentation!

Enter a number: a
Traceback (most recent call last):
File "./tro.py", line 3, in <module>
x=int(raw_input("Enter a number: "))
ValueError: invalid literal for int() with base 10: ’a’

The error is a ↓ValueError. The ’rawinput’ is wrapped with ’int()’. This line expected an integer and you substituted an integer with a letter. To guide the user to enter the correct type of data, we rewrite ’tro.py’ with the following information.

#!/usr/bin/python
#tro1.py
try:
	x=int(raw_input("Enter a number: "))
	print x
except ValueError:
	print "You did not enter a number"

Another way to write it:

#!/usr/bin/python
#tro2.py
try:
	x=int(raw_input("Enter a number: "))
	print x
except:
	print "You did not enter a number"

This would be considered a ↓catch all for ↓multiple exceptions. However, this is not good programming practice. It’s recommended that you understand the different types of exceptions that could occur. It’s very easy to have multiple exceptions for a routine block of code. For example:

#!/usr/bin/python
#try3.py
try:
	x=int(raw_input("Enter a number: "))
	print x
except EOFError: print "why did you exit early"
	except ValueError:
		print "You did not enter a number"

Run this program (Do not enter a number or letter) then type ’Ctrl-d’ to exit the program. . When you exit early, you hit the EOF error or ’End Of File’. ↓.

5.1.1 Raise Exception

There are cases in which you want to your program to operate as intended and still raise an exception when needed. You can create your own exceptions and raise them yourself. The following demonstrates how to raise your own exceptions. Don’t forget to ’import sys’ package.

#!/usr/bin/python
#raise.py
import sys
def letserror():
	raise RuntimeError(’Force the error’)
def main():
	letserror()
main()

Results: the line numbers could be a little different:

Pay ATTENTION to indentation!

Traceback (most recent call last):
File "raise.py", line 7, in <module>
main()
File "raise.py", line 6, in main
letserror()
File "raise.py", line 4, in letserror
raise RuntimeError(’Force the error’)
	RuntimeError: Force the error

However this does not look so clean. Below is a slight modification:

#!/usr/bin/python
#raise2.py
import sys
def letserror():
	raise RuntimeError(’Force the error’)
def main(num):
	try:
		letserror()
	except Exception, err:
		sys.stderr.write(str(err))
main(0)

You do have quite a bit control in how you print your error messages out. For example you could replace ’sys.stderr.write’ with the following: ”sys.stderr.write("%s\n" % str(err))”. The object ’sys.stderr’ is part of the Unix standard input, output and error pipe. Let’s put this into action. Here is a more practical example:

#!/usr/bin/python
#raise3.py
import sys
def letserror():
	raise RuntimeError(’Force the error’)
def main(num):
	try:
		if num < 3:
			letserror()
		else:
			blah=num*num
			print "my number is", blah
	except Exception, err:
		sys.stderr.write("%s your number %s is less than 3\n" % (str(err),num))
main(2)

If you change ’main(2)’ to ’3’ it will square your number, however if it’s less than ’3’ or (< 3), the error will raise and you can give the user a detailed explanation.

5.1.2Finally

The finally stanza is guaranteed to run even if the try block raises an exception. This makes it ideal for cleanup or ’close()’. For example:

#!/usr/bin/python
#raise4.py
import sys
def letserror():
	raise RuntimeError(’Force the error’)
def main(num):
	try:
		if num < 3:
			letserror()
		else:
			blah=num*num
			print "my number is", blah
	except Exception, err:
		sys.stderr.write("%s your num %s less than 3\n" % (str(err),num))
	finally:
		print "okay I could close the file or end this etc..."
main(2)

You will notice that the finally stanza runs if an error is raised or not.

5.1.3 Best Practice

Plenty of examples have been listed above. At the very least, the base exception class ’Exception(Base Exception)’ should be utilized as a default solution for handling multiple cases. Try it with a letter, number, or no data, and ’ctrl-z’.

try:
	x=int(raw_input(“Enter a number: “))
exception Exception, e:
	print e

5.1.4 Ignore ↓Exception

Add ’pass’ which is a null operation.

try:
	x=int(raw_input(“Enter a number: “))
exception Exception, e:
	pass

5.1.5 Summary

Make every effort to master exception handling because it will save you when troubleshooting code and more than likely improve the quality of your software development. No exercises are required in this section because you should continue the practice of implementing exception handling moving forward.


To post a comment you need to login first.