Python Concepts/Try Statement
Objective[edit | edit source]
|
Page Index[edit | edit source]
|
Lesson[edit | edit source]Errors and Exceptions[edit | edit source]In a perfect world, nothing goes wrong. Unfortunately, we don't live in a perfect world, so bad things are bound to happen. Computers can crash, monitors can short, and hard drives can corrupt. In the event that something goes wrong, purposely or not, the computer needs to be able to understand that something is going wrong and stop/fix the problem. Software also needs to be able to handle these problems, too. Errors happen when something doesn't go right. For example, pulling a CD out of a computer while burning something on it will result in the CD not being completely finished (corrupted) and it will also make the CD unavailable to the software using it (the CD burning program). If the program can't handle this problem it might display undefined behavior, like trying to continue burning to a nonexistent CD or the program could just hang. That's not very helpful to the user, so it's important to take care of these errors. Luckily, Python is able to handle errors and exceptions, unlike other programming languages. Python Errors vs. C Errors[edit | edit source]As we've seen so far in this course, errors are very loud in Python. If something doesn't follow the rules or doesn't go right, Python will make sure you hear about it. Having every little mistake scrutinized without mercy might sound bad at first, but it actually becomes a vital necessity when you learn why. Early programming languages, like C, didn't come with built-in error handling. Sometimes errors went by unnoticed. Other times they caused the computer to crash. It was up to the programmer to create their own error handling support and even then it was still hard to catch errors in their tracks. Python's ultimate error handling goal is to let you know that an error has occurred. Having fulfilled its goal, what happens next is all up to you. If you don't specify anything to happen, then a default error message is displayed and the program is ended. Loud Errors[edit | edit source]Now that we have a bigger picture on errors, it becomes clear that handling errors is important. Imagine creating a large program. The said program crashes when you use it. It then becomes really important on finding and fixing the problem. Python lets you know where the error occurred and what caused the error. This simplifies the error fixing process and it allows for rapid development with the knowledge that errors don't go unnoticed. This is one of the many situations where error handling comes in handy. The Try and Except Statements[edit | edit source]Python allows for errors and exceptions to be handled by the program. To do so, you'll need to use both the >>> try:
... print(spam)
... except:
... print("spam isn't defined!")
...
spam isn't defined!
If any code within the Now, you might have noticed that error messages will identify what kind of error happened on the third line. In the case of the earlier example, a Now, what happens if we want to catch a specific error like >>> try:
... print(spam)
... except NameError:
... print("spam isn't defined!")
... except:
... print("An unknown error has occurred!")
...
spam isn't defined!
We can see that the Exceptions[edit | edit source]
The Else Statement[edit | edit source]The >>> try:
... spam = 7
... print("I have %d cans of spam!" % spam)
... except:
... print("Some error has occurred!")
... else:
... print("Everything went smoothly!")
...
I have 7 cans of spam!
Everything went smoothly!
The Finally Statement[edit | edit source]The >>> try:
... print("pop")
... except:
... print("An error has occurred!")
... else:
... print("Everything went smoothly!")
... finally:
... print("Finishing up now...")
...
pop
Everything went smoothly!
Finishing up now...
>>> try:
... print("soda")
... except:
... print("An error has occurred!")
... finally:
... print("Cleaning up any mess...")
...
soda
Cleaning up any mess...
|
Examples[edit | edit source]Python has powerful error detection capabilities. If it's possible to produce an error (and it usually is), Python is ready to pounce on it and broadcast to the world if an error has occurred. It's the responsibility of the programmer to anticipate and handle errors so that, despite errors, the job completes successfully or terminates gracefully. We software engineers should be grateful for Python's error detection power; we can spend less time chasing errors and more time writing good code.
>>> if a == 6 : print ('a = 6')
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>>
>>> a = 4 ; if a == 6 print ('a = 6')
File "<stdin>", line 1
a = 4 ; if a == 6 print ('a = 6')
^
SyntaxError: invalid syntax
>>>
>>> a = '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: must be str, not int
>>>
>>> a = [0,1,2,3,4] ; a[5]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>>
>>> votes = ["yes", "no", "yes", "yes", "no"]
>>> votes.index("maybe")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 'maybe' is not in list
>>>
>>> a = {} ; a['Bill']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Bill'
>>>
>>> a = array('B', [1,2,3,4]) ; a[2] = 0xfff
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: unsigned byte integer is greater than maximum
>>>
>>> 2/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> # The above exits with status = 1.
>>>
Python's try :
2 / 0
except ZeroDivisionError :
print ('Division by 0 detected.') # This printed
The above exits with status = 0 and there is no output to stderr. try :
2 / 0
except ZeroDivisionError :
print ('Division by 0 detected.')
except :
exit (0)
File "t3.py", line 9 exit (0) ^ IndentationError: expected an indented block try :
a = [1,2,3] ; a[4]
except Indexerror :
print ('Indexerror detected.')
except :
print ('Unknown error detected.')
Traceback (most recent call last): File "t3.py", line 5, in <module> a =[1,2,3]; a[4] IndexError: list index out of range During handling of the above exception, another exception occurred: Traceback (most recent call last): File "t3.py", line 6, in <module> except Indexerror : NameError: name 'Indexerror' is not defined The example above stresses that the code processing errors should not introduce another error. Correct the spelling mistake and try again: try :
a = [1,2,3] ; a[4]
except IndexError :
print ('IndexError detected.') # This prints and the code exits with status = 0.
except :
print ('Unknown error detected.')
The following code tests a selection of different errors, including errors raised by the code and also
an error import sys
class label(Exception): pass # declare a label
for condition in range(1, 17) :
print ('\ncondition = {}. '.format(condition), end='')
try :
if condition == 1 : 2 / 0
elif condition == 2 : a = [1,2,3] ; a[4]
elif condition == 3 : b = c
elif condition == 4 : a = '2' + 2
elif condition == 5 : a = {} ; a['Bill']
elif condition == 6 : b = array('B', [1,2,3,4]) ; b[2] = 0xfff
elif condition == 7 : raise ZeroDivisionError
elif condition == 8 : raise IndexError
elif condition == 9 : raise NameError
elif condition == 10 : raise TypeError
elif condition == 11 : raise KeyError
elif condition == 12 : raise OverflowError
elif condition == 13 : raise label()
elif condition == 14 : raise IndentationError
elif condition == 15 : raise UnicodeError
except ZeroDivisionError : print ('ZeroDivisionError detected.')
except IndexError : print ('IndexError detected.')
except NameError : print ('NameError detected.')
except TypeError : print ('TypeError detected.')
except KeyError : print ('KeyError detected.')
except OverflowError : print ('OverflowError detected.')
except label : print ('Arrived at label.')
except :
print ('Unknown error detected:')
a = sys.exc_info() # Info about unknown error that caused exception.
print (' ', a)
b = [ str(p) for p in a ]
print (' ', b)
else : print ('Smooth sailing.')
sys.exit (0)
condition = 1. ZeroDivisionError detected. condition = 2. IndexError detected. condition = 3. NameError detected. condition = 4. TypeError detected. condition = 5. KeyError detected. condition = 6. NameError detected. condition = 7. ZeroDivisionError detected. condition = 8. IndexError detected. condition = 9. NameError detected. condition = 10. TypeError detected. condition = 11. KeyError detected. condition = 12. OverflowError detected. condition = 13. Arrived at label. condition = 14. Unknown error detected: (<class 'IndentationError'>, IndentationError(), <traceback object at 0x101a43dc8>) ["<class 'IndentationError'>", 'None', '<traceback object at 0x101a43dc8>'] condition = 15. Unknown error detected: (<class 'UnicodeError'>, UnicodeError(), <traceback object at 0x101a50b48>) ["<class 'UnicodeError'>", '', '<traceback object at 0x101a50b48>'] condition = 16. Smooth sailing.
|
Testing your code
[edit | edit source]
Thorough testing of your code requires that you deliberately subject your code to all sorts of error conditions and then check that the code handles all errors gracefully. If an error condition causes your program to halt (and it usually does), restarting the application to continue testing for other error conditions can be very time-consuming. Python's This section describes a simple example full of errors that are all handled very simply and gracefully
with Python's Password checking[edit | edit source]Suppose that your piece of code checks a password for "strength." The usual requirements are that the password should be a certain length, that it should contain or should not contain certain characters and so on. Preparation[edit | edit source]The following piece of code includes extra tests to reject substrings such as "hijk", "ponm", "qwerty" or "9876". Hopefully the error messages in the code are self explanatory. import re
import sys
UPPER = 'QWERTYUIOPASDFGHJKLZXCVBNM' #according to keyboard.
UPPER1 = ''.join(sorted(list(UPPER))) #according to alphabet.
lower = 'qwertyuiopasdfghjklzxcvbnm' #according to keyboard.
lower1 = ''.join(sorted(list(lower))) #according to alphabet.
number = '1234567890'
symbol = '''!@#$%^&*()+{}|:<>?'''
tuple1 = (
"UPPER", # Password must contain at least 4 different UPPER characters,
# but not in one group in either keyboard or alphabetic sequence,
# forward or reversed. Same conditions apply below.
"UPPER1", # Used to ensure that password does not contain groups from alphabet.
"lower", # Password must contain at least 4 different lower characters.
"lower1", # Used to ensure that password does not contain groups from alphabet.
"number", # Password must contain at least 2 different number characters.
"symbol", # Password must contain at least 3 different symbol characters.
)
def checkIt (pw) :
if not isinstance (pw, str) :
print ('checkIt (pw) : Input must be string.')
exit(99)
if 24 >= len(pw) >= 16 : pass
else :
print ('checkIt (pw) : Input not correct length.')
exit(98)
for name_ in tuple1 :
characters = eval(name_)
while 1 :
if len(characters) > 20 : value = 4 ; break
if len(characters) > 10 : value = 3 ; break
value = 2 ; break
if len( set(characters) & set(pw) ) < value :
print ('checkIt (pw) : Password must contain at least {} different {} characters.'.format(value, name_))
exit(97)
for p in range (0,len(characters)-(value-1)) :
v1 = characters[p:p+value]
if v1 in pw :
print ('checkIt (pw) : {} adjacent {} characters must not appear in password: {}'.format(value, name_,v1) )
exit(96)
v1 = v1[::-1]
if v1 in pw :
print ('checkIt (pw) : {} adjacent {} characters (reversed) must not appear in password: {}'.format(value, name_,v1) )
exit(95)
for c in pw :
if ( (c in UPPER) or
(c in lower) or
(c in number) or
(c in symbol) or
(c == '_') ) : pass
else :
print ('checkIt (pw) : Character in password not recognized:', c)
exit(94)
#
# More testing.
#
return True
Sample passwords[edit | edit source]In the next piece of code there is a string containing 20 sample passwords, all of which except one fail the test. The passwords in the string are converted to commands within list "instructions". samples = """
2345678
2341234567890123456789012345678905678
4562341234567890123
BCDE4234{}345678`0123
JIHG4234{}345678`0123
UIOP4234{}345678`0123
LKJH4234{}345678`0123
HGMEd{}!@#$%^&*()_+=
cdef_HGMEd{}!@#$%^&*()_+
ponm_HGMEd{}!@#$%^&*()_+
erty_HGMEd{}!@#$%^&*()_+
hgfd_HGMEd{}!@#$%^&*()_+
hgxd_HGMEd{}!@#$%^&*()_+
23_hgxd_HGMEd{}!@#$%^&*(
65_hgxd_HGMEd{}!@#$%^&*(
39_hgxd_HGMEdchdtsbche
39_hgxd_HGMEdchdts^&*e
39_hgxd_HGMEdchdts%$#e
39_hgxd_HGMEdch;s*#%e
39_hgxd_HGMEdchdts*#%e
"""
L1 = [ p for p in re.split(r'\s{0,}\n\s{0,}', samples) if p ]
L2 = [ 'checkIt("' + p + '")' for p in L1 ]
instructions = [
'checkIt()',
'checkIt(1,2,3,4)',
'checkIt(5)',
] + L2
print ('\n'.join(instructions))
checkIt()
checkIt(1,2,3,4)
checkIt(5)
checkIt("2345678")
checkIt("2341234567890123456789012345678905678")
checkIt("4562341234567890123")
checkIt("BCDE4234{}345678`0123")
checkIt("JIHG4234{}345678`0123")
checkIt("UIOP4234{}345678`0123")
checkIt("LKJH4234{}345678`0123")
checkIt("HGMEd{}!@#$%^&*()_+=")
checkIt("cdef_HGMEd{}!@#$%^&*()_+")
checkIt("ponm_HGMEd{}!@#$%^&*()_+")
checkIt("erty_HGMEd{}!@#$%^&*()_+")
checkIt("hgfd_HGMEd{}!@#$%^&*()_+")
checkIt("hgxd_HGMEd{}!@#$%^&*()_+")
checkIt("23_hgxd_HGMEd{}!@#$%^&*(")
checkIt("65_hgxd_HGMEd{}!@#$%^&*(")
checkIt("39_hgxd_HGMEdchdtsbche")
checkIt("39_hgxd_HGMEdchdts^&*e")
checkIt("39_hgxd_HGMEdchdts%$#e")
checkIt("39_hgxd_HGMEdch;s*#%e")
checkIt("39_hgxd_HGMEdchdts*#%e")
Testing each password[edit | edit source]The next piece of code tests each password. for instruction in instructions :
error = ''
print ('\ntrying', instruction)
try : exec (instruction)
except : error = str(sys.exc_info())[1:-1]
if error :
class_, remainder = re.split(r'\>\,\s', error)
class_ = class_ + '>'
text,traceback = re.split (r'\,\s\<', remainder)
traceback = '<' + traceback
print ('''error detected:
{}
{}
{}
'''.format( class_, text, traceback ), end='')
Results[edit | edit source]trying checkIt()
error detected:
<class 'TypeError'>
TypeError("checkIt() missing 1 required positional argument: 'pw'",)
<traceback object at 0x10294f208>
trying checkIt(1,2,3,4)
error detected:
<class 'TypeError'>
TypeError('checkIt() takes 1 positional argument but 4 were given',)
<traceback object at 0x10294f188>
trying checkIt(5)
checkIt (pw) : Input must be string.
error detected:
<class 'SystemExit'>
SystemExit(99,)
<traceback object at 0x10294f248>
trying checkIt("2345678")
checkIt (pw) : Input not correct length.
error detected:
<class 'SystemExit'>
SystemExit(98,)
<traceback object at 0x10294f288>
trying checkIt("2341234567890123456789012345678905678")
checkIt (pw) : Input not correct length.
error detected:
<class 'SystemExit'>
SystemExit(98,)
<traceback object at 0x10294f1c8>
trying checkIt("4562341234567890123")
checkIt (pw) : Password must contain at least 4 different UPPER characters.
error detected:
<class 'SystemExit'>
SystemExit(97,)
<traceback object at 0x10294f308>
trying checkIt("BCDE4234{}345678`0123")
checkIt (pw) : 4 adjacent UPPER1 characters must not appear in password: BCDE
error detected:
<class 'SystemExit'>
SystemExit(96,)
<traceback object at 0x10294f188>
........................................
........................................
........................................
trying checkIt("39_hgxd_HGMEdchdtsbche")
checkIt (pw) : Password must contain at least 3 different symbol characters.
error detected:
<class 'SystemExit'>
SystemExit(97,)
<traceback object at 0x10294f188>
trying checkIt("39_hgxd_HGMEdchdts^&*e")
checkIt (pw) : 3 adjacent symbol characters must not appear in password: ^&*
error detected:
<class 'SystemExit'>
SystemExit(96,)
<traceback object at 0x10294f348>
trying checkIt("39_hgxd_HGMEdchdts%$#e")
checkIt (pw) : 3 adjacent symbol characters (reversed) must not appear in password: %$#
error detected:
<class 'SystemExit'>
SystemExit(95,)
<traceback object at 0x10294f2c8>
trying checkIt("39_hgxd_HGMEdch;s*#%e")
checkIt (pw) : Character in password not recognized: ;
error detected:
<class 'SystemExit'>
SystemExit(94,)
<traceback object at 0x10294f188>
trying checkIt("39_hgxd_HGMEdchdts*#%e")
|
Assignments[edit | edit source]
|
|
References
[edit | edit source]- ↑ Python Software Foundation. "Exception hierarchy" (HTML). Built-in Exceptions. Retrieved 2015-05-05.
1. Python's documentation:
"8. Errors and Exceptions" "8.4. The try statement"
2. Python's methods:
3. Python's built-in functions: