Python Exceptions

Python-Exceptions

With thanks to Dr. Eric Zhao from the Finance Mathematics Program, BNU-HKBU United International College

What is Exception?

  • An exception is an event, which occurs during the execution of a program that disrupts the normal flow of the program’s instructions. In general, when a Python script encounters a situation that it cannot cope with, it raises an exception.

  • An exception is a Python object that represents an error.

  • When a Python script raises an exception, it must either handle the exception immediately otherwise it terminates and quits.

[!example ]- Example 1

fileDir = ''
f = open(fileDir, 'r')
f.close()
  • Explanation: Since Python cannot find the file under fileDir, it will raise IOError immediately. The program will terminate and Python will quit.

  • Python has many built-in Exceptions. You can check here.

  • In some cases, you would know that some suspicious code may raise an exception (e.g. irregular user input), you can defend your program by placing the suspicious code in a try block, and handles the potential exceptions explicitly in except block.

  • This is very helpful to write strong and reliable code.

Handling an exception

Syntax

try: # You do your error prone operations here;
	#statement2
	#statement3
except Exception1:
	#If there is Exception1, then execute this block.
except Exception2:
	#If there is Exception2, then execute this block.
else:
	#If there is no exception then execute this block.

Workflow

  • It works in the following way:

  • First all lines between try and except statements.

  • If ExceptionName happens during execution of the statements then except clause statements execute

  • If no exception happens then the statements inside except clause does not execute.

  • If the Exception is not handled in the except block then it goes out of try block.

Attention

  • Here are few important points about the above-mentioned syntax:

  • A single try statement can have multiple except statements. This is useful when the try block contains statements that may throw different types of exceptions.

  • You can also provide a generic except clause, which handles any exception.

  • After the except clause(s), you can include an else clause. The code in the else block executes if the code in the try block does not raise an exception.

  • The else block is a good place for code that does not need the try block’s protection.

[!example]- Example-2

fh = open('testfile.txt', 'r')
s = fh.read()
fh.close()
print(s)
try:
	fh = open('testfile.txt', 'r')
	s = fh.read()
	fh.close()
	print(s)
except FileNotFoundError:
	print ("Error: can't find file")
else:
	print ("Read succeeded!")
print ("Haha") # Always printed

Output

Error: can't find file
Haha

The result depends on whether your current directory contains the testfile.txt. If exists, the file will be read and then the else statement will be executed. If not, except FileNotFoundError will be executed.

[!example]- Example 3

def get_number():
#"Returns a float number"
	number = float(input("Enter a float number: "))
	return number
  
i = 0.0
while i != 8.0:
	try:
		i = get_number()
	except ValueError:
		print ("You entered a wrong value.")
	else:
		print ('There is no error. i is:', i)
	print ('haha') # Always printed every time around the loop
print('after loop') # Always printed

Output

Enter a float number: 8.0
There is no error. i is: 8.0
haha
after loop

The except Clause with No Exceptions (Default Exception)

  • You can also use the except statement with no exceptions defined as follows
try:
	#You do your operations here;
except:
	#If there has exception, then execute this block.
else:
	#If no exception then execute this block.
  • This kind of a try-except statement catches all the exceptions that occur. Using this kind of try-except statement is not considered a good programming practice though, because it catches all exceptions but does not make the programmer identify the root cause of the problem that may occur.
try:
	assert int(input('Input a value: ')) == 3
except ValueError:
	print ('Input type is not appropriate')
except:
	print ('Other errors like assertion error')  
print ('If the error is handled, then you can see this.')

Output

Input a value: 3
If the error is handled, then you can see this.

The try-finally Clause

  • You can use a finally block along with a try block. The finally block is a place to put any code that must execute, whether the try block raised an exception or not. The syntax of the try-finally statement is:
try:
	#You do your operations here;
except <expeciton>:
	#Due to any exception, this may be skipped.
finally:
	#This would always be executed.

[!example]- Example 4

def testFunc():
	try:
		f = open('test.txt', 'w') # Succeeds
		f.dummyFunction() # Exception here
	except AttributeError:
		print ('Exception appears happening here')
		return # no matter what, "finally" will be executed
	finally:
		print ('I am finally here')
		f.close() # We always close the file, even when doing return  
		
testFunc()

Output

Exception appears happening here
I am finally here

Raise user defined Exception

  • You can create your own exception by inheriting the Python built-in Exception class.

  • When certain condition meets, you can raise the exception object which is defined.

class ShortInputException(Exception): # inherit from the "Exception" class
	'''A user-defined exception class containing two variables.'''
	def __init__(self, length, atleast):
		Exception.__init__(self)
		self.length = length
		self.atleast = atleast
	def shortInputExceptionAction(self):
		print ('shortInputException can do many operations here')
		print ('Your input length %d, but the length should be at least %d'% (self.length, self.atleast))

try:
	s = input('Enter Something: ')
	if len(s) < 3:
	raise ShortInputException(len(s), 3) # create and raise (activate) your own Exception object

except KeyboardInterrupt: # When using the Kernel -> Interrupt menu

print ('Why did you do interrupt me?')

except ShortInputException as x: # x is now the name for the exception object which is handled in this block

x.shortInputExceptionAction()

else:

print ('No exception was raised.')

Enter Something: 3333

No exception was raised.

  • You can create as many exception classes as needed.

Example 5


class ShortInputException(Exception):

'''A user-defined exception class.'''

def __init__(self, length, atleast):

Exception.__init__(self)

self.length = length

self.atleast = atleast

  

def shortInputExceptionAction(self):

print ('shortInputException can do many operations here')

print ('Your input length %d, but the length should be at least %d'% (self.length, self.atleast))

  

class LongInputException(Exception):

'''A user-defined exception class.'''

def __init__(self, length, atmost):

Exception.__init__(self)

self.length = length

self.atmost = atmost

  

def longInputExceptionAction(self):

print ('longInputExceptionAction can do many operations here')

print ('Your input length %d, but the length should be at most %d'% (self.length, self.atmost))


try:

s = input('Enter Something: ')

if len(s) < 3:

raise ShortInputException(len(s), 3) # raise your own Exception object

if len(s) > 7:

raise LongInputException(len(s), 7)

except KeyboardInterrupt: # When using the Kernel -> Interrupt menu

print ('Why did you do interrupt me?')

except ShortInputException as x: # x is the "ShortInputException" object

x.shortInputExceptionAction()

except LongInputException as x:

x.longInputExceptionAction()

else:

print ('No exception was raised.')

Enter Something: 33333

No exception was raised.

3. Assertions in Python

  • The assert statement will help you check the validity of an expression. If the expression is false, Python raises an AssertionError exception.

  • Programmers often place assertions to check whether the input or the result obtained fulfills the expectation.

Syntax


assert Expression[, ArgumentExpression]

  • If the assertion fails, Python uses ArgumentExpression as the argument for the AssertionError. AssertionError exceptions can be caught and handled like any other exception using the try-except statement, but if not handled, they will terminate the program and produce a traceback.

Example 5


def KelvinToFahrenheit(Temperature):

# assert Temperature >= 0, "So cold, temperature below zero"

return (Temperature - 273) * 1.8 + 32

  

print (KelvinToFahrenheit(273))

print (int(KelvinToFahrenheit(505.78)))

print (KelvinToFahrenheit(-5))

32.0

451

-468.40000000000003


def KelvinToFahrenheit(Temperature):

try:

assert Temperature >= 0

return (Temperature - 273) * 1.8 + 32

except AssertionError:

print ('So cold, temperature below zero')


KelvinToFahrenheit(-10)

So cold, temperature below zero

Task 1: Complete the function divide which takes two strings, m and n as the arguments. The function should return m/n as the result.

Note that

  • if m or n are not numbers, the function should return 'Error: Not numbers';

  • if n is zero, the function should return 'Error: Zero divisor'.

You program should not crash in any of the cases above.

Note: You are NOT allowed to use any if-branches!


def divide(m, n):

try:

# Attempt to convert strings to floats

m = float(m)

n = float(n)

result = m / n # This can raise a ZeroDivisionError

return result

except ZeroDivisionError: # Handle division by zero

return 'Error: Zero divisor'

except ValueError: # Handle non-numeric values

return 'Error: Not numbers'


assert divide('2', 'haha') == 'Error: Not numbers'

assert divide('haha', '0') == 'Error: Not numbers'

assert divide('2','0') == 'Error: Zero divisor'

assert divide(10, 2) == 5.0


# This cell contains hidden tests, do NOT delete!


# This cell contains hidden tests, do NOT delete!


# This cell contains hidden tests, do NOT delete!


# This cell contains hidden tests, do NOT delete!

Task 2: Complete the function robustLog which takes two strings, b and x as the arguments. The function should first convert b and x to real numbers and then return $log_bx$.

Note that

  • if b or x are not real numbers, the function should return 'Error: Not real';

  • if b or x are not positive, the function should return 'Error: Non-positive values';

  • if b equals to 1, the function should return 'Error: Zero divisor'.

You program should not crash in any of the cases above.

Hint: To compute the logarithm, You can import math and use math.log().

Note: You are NOT allowed to use any if-branches!


  

import math

def robustLog(b, x):

try:

b = float(b)

x = float(x)

# Check for errors using assertions which will raise an AssertionError if conditions fail

assert b > 0 and x > 0, 'Error: Non-positive values'

assert b != 1, 'Error: Zero divisor'

return math.log(x, b)

except ValueError: # Handle conversion errors

return 'Error: Not real'

except AssertionError as error: # Handle assertions

return str(error)

  
  


assert robustLog('haha','10') == 'Error: Not real'

assert robustLog('1','haha') == 'Error: Not real'

assert robustLog('2','0') == 'Error: Non-positive values'

assert robustLog('-1','3') == 'Error: Non-positive values'

assert robustLog('1','-3') == 'Error: Non-positive values'

assert robustLog('1','3') == 'Error: Zero divisor'

assert robustLog('2','8') == 3


# This cell contains hidden tests, do NOT delete!


# This cell contains hidden tests, do NOT delete!


# This cell contains hidden tests, do NOT delete!


# This cell contains hidden tests, do NOT delete!


# This cell contains hidden tests, do NOT delete!

BackLink