Professional Documents
Culture Documents
Exceptional Handling
Exceptional Handling
Exceptional Handling
Hello
print('Hello)
File
"C:\Users\sunny\AppData\Local\Temp/ipykernel_35952/1679058590.py",
line 1
print('Hello)
^
SyntaxError: EOL while scanning string literal
Note how we get a SyntaxError, with the further description that it was an End of Line
Error (EOL) while scanning the string literal. This is specific enough for us to see that we
forgot a single quote at the end of the line. Understanding of these various error types will
help you debug your code much faster.
This type of error and description is known as an Exception. Even if a statement or
expression is syntactically correct, it may cause an error when an attempt is made to
execute it. Errors detected during execution are called exceptions and are not
unconditionally fatal.
Exception description
Exception Base class of exception. Allother exception
derived from this class.
ArithmeticError Base class for those exceptions that are
raised for arithmetic or numeric errors.
ZeroDivisionError Raised when division or modulo operation
is zero
ModuleNotFoundError Raised by import when imported module
could not be located
KeyError Raised when a mapping (dictionary) key is
not found in keys of a dictionary.
MemoryError Raised when an operation runs out of
memory
You can check out the full list of built-in exceptions here. Now, let's learn how to handle
errors and exceptions in our own code.
In python, There are two popular saying for code styles:-
1) LBYL
2) EAFP
LBYL
Look before you leap. This coding style explicitly tests for pre-conditions before making
calls or lookups. This style contrasts with the EAFP approach and is characterized by the
presence of many if statements.
In a multi-threaded environment, the LBYL approach can risk introducing a race condition
between “the looking” and “the leaping”. For example, the code, if key in mapping: return
mapping[key] can fail if another thread removes key from mapping after the test, but
before the lookup. This issue can be solved with locks or by using the EAFP approach.
For this, you can refer in python documentation:-
** https://docs.python.org/3/glossary.html **
In a simple language, we first check what we are going to do. For example, if we want to
check if a file is available before trying to write:
if filename:
with open()..
....
EAFP
Easier to ask for forgiveness than permission.
This common Python coding style assumes the existence of valid keys or attributes and
catches exceptions if the assumption proves false. This clean and fast style is characterized
by the presence of many try and except statements. The technique contrasts with the LBYL
style common to many other languages such as C.
In a simple language,EAFP is like we first write our code so that it performs and executes
first, and then we will take care of the consequences if it doesn't work. That means we try
running some code, expecting it to work, but if it failes then will handle it in exception in
except block.
try:
with open(filename,'r').. # First executes
....
except:
# handling exception
Using just except, we can check for any exception: To understand better let's check out a
sample code that opens and writes a file:
try:
f = open('demo_file','w')
f.write('Test write this')
except IOError:
# This will only check for an IOError exception and then execute
this print statement
print("Error: Could not find file or read data")
else: # this else block will execute if try block does not raise an
exception
print("Content written successfully")
f.close()
Now, let's see what happens when we don't have write permission? (opening only with 'r'):
f = open('demo_file','r')
f.write('Test write this')
print("fsfsfsfsf")
----------------------------------------------------------------------
-----
UnsupportedOperation Traceback (most recent call
last)
<ipython-input-2-7498bff3140a> in <module>
1 f = open('testfile','r')
----> 2 f.write('Test write this')
3 print("fsfsfsfsf")
try:
f = open('demo_file','r')
f.write('Test write this')
except IOError:
# This will only check for an IOError exception and then execute
this print statement
print("Error: Could not find file or read data")
else:
print("Content written successfully")
f.close()
Notice, how we only printed a statement! The code still ran and we were able to continue
doing actions and running code blocks. This is extremely useful when you have to account
for possible input errors in your code. You can be prepared for the error and keep running
code, instead of your code just breaking as we saw above.
We could have also just said except: if we weren't sure what exception would occur. For
example:
try:
f = open('testfile','r')
f.write('Test write this')
except:
# This will check for any exception and then execute this print
statement
print("Error: Could not find file or read data")
else:
print("Content written successfully")
f.close()
Now, we don't actually need to memorize the list of exception types! Now what if we keep
wanting to run code after the exception occurred? This is where finally comes in.
finally
The finally: Block of code will always be run regardless if there was an exception in the try
code block. The syntax is:
try:
Code block here
...
Due to any exception, this code may be skipped!
finally:
This code block would always be executed.
For example:
try:
f = open("testfile", "w")
f.write("Test write statement")
finally:
print("Always execute finally code blocks")
We can use this in conjunction with except. Let's see a new example that will take into
account a user putting in the wrong input:
def askint():
try:
val = int(input("Please enter an integer: "))
except:
print("Looks like you did not enter an integer!")
finally:
print("Finally, I executed!")
print(val)
askint()
askint()
----------------------------------------------------------------------
-----
UnboundLocalError Traceback (most recent call
last)
<ipython-input-8-cc291aa76c10> in <module>
----> 1 askint()
<ipython-input-6-1b367de9a831> in askint()
7 finally:
8 print("Finally, I executed!")
----> 9 print(val)
Check how we got an error when trying to print val (because it was properly assigned).
Let's find the right solution by asking the user and checking to make sure the input type is
an integer:
def askint():
try:
val = int(input("Please enter an integer: "))
except:
print("Looks like you did not enter an integer!")
try:
val = int(input("Try again-Please enter an integer:
"))
except:
print("handle it ")
finally:
print("Finally, I executed!")
askint()
Hmmm...that only did one check. How can we continually keep checking? We can use a
while loop!
def askint():
while True:
try:
val = int(input("Please enter an integer: "))
except:
print("Looks like you did not enter an integer!")
break
else:
print('Yep thats an integer!')
break
finally:
print("Finally, I executed!")
print(val)
askint()
Please enter an integer: five
Looks like you did not enter an integer!
Finally, I executed!
----------------------------------------------------------------------
-----
UnboundLocalError Traceback (most recent call
last)
<ipython-input-15-cc291aa76c10> in <module>
----> 1 askint()
<ipython-input-14-9682f0bcb1dc> in askint()
11 finally:
12 print("Finally, I executed!")
---> 13 print(val)
Raising an exception
We can raise an excepton by using raise statement. Let us check with examples:-
def raise_exc(a):
if a < 5:
raise Exception(a) # If exception raised code below to this
will not execute
return a
try:
res1 = raise_exc(7)
print(res1)
res = raise_exc(2)
print(res)
except Exception as e:
print("Error is ", e)
7
Error is 2
try:
raise(NewError(5))
except NewError as e:
print('A New Exception occured: ',e.val)
Assertion
Python's assert statement helps you find bugs more quickly and with less pain.
Assertions are a systematic way to check that the internal state of a program is as the
programmer expected, with the goal of catching bugs. In particular, they're good for
catching false assumptions that were made while writing the code, or abuse of an interface
by another programmer. In addition, they can act as in-line documentation to some extent,
by making the programmer's assumptions obvious. ("Explicit is better than implicit.")
For more,
Refer:- https://wiki.python.org/moin/UsingAssertionsEffectively
from IPython.display import Image
Image(filename='img/assertion.png')
# Looping through list and print division of given element with the
element itself if element is int else raise exception
list1 = ['a', 0, 2] # For str 'a' raise error, for 0 raise zero
division error
for el in list1:
try:
print("The element is", el)
res = int(el)/int(el)
break
except Exception as e:
print("Oo!", e, "occurred.")
print("Next check for another element in a list.")
print()
print(res)
The element is a
Oo! invalid literal for int() with base 10: 'a' occurred.
Next check for another element in a list.
The element is 0
Oo! division by zero occurred.
Next check for another element in a list.
The element is 2
1.0
Enter a number: 32
Executing else block as try block hasn't raise an exception.
# Use of lambad function with exception raise if value < 10 will raise
an exception
y = lambda x: 2*x if x < 10 else raise_exception(Exception('Value is
greater than 10'))
y(5)
10
y(20)
----------------------------------------------------------------------
-----
Exception Traceback (most recent call
last)
<ipython-input-57-69bf4e317ad3> in <module>
----> 1 y(20)
<ipython-input-55-99236a7fd7fe> in <lambda>(x)
1 # Use of lambad function with exception raise if value < 10
will raise an exception
----> 2 y = lambda x: 2*x if x < 10 else
raise_exception(Exception('Value is greater than 10'))
<ipython-input-54-a8f242b090b9> in raise_exception(ex)
1 # Defining function for raising exception
2 def raise_exception(ex):
----> 3 raise ex
# defining function for finding sqrt and checking type of number and
raise exception if not an int/float
import math
def find_sqrt(a):
if not isinstance(a,(int,float)):
raise TypeError("a must be numeric")
elif a < 0:
raise TypeError("a should not be negative")
else:
print(math.sqrt(a))
find_sqrt("scsc")
----------------------------------------------------------------------
-----
TypeError Traceback (most recent call
last)
<ipython-input-2-31a3948965a9> in <module>
----> 1 find_sqrt("scsc")
<ipython-input-1-e201b0a49914> in find_sqrt(a)
3 def find_sqrt(a):
4 if not isinstance(a,(int,float)):
----> 5 raise TypeError("a must be numeric")
6 elif a < 0:
7 raise TypeError("a should not be negative")
find_sqrt(-56)
----------------------------------------------------------------------
-----
TypeError Traceback (most recent call
last)
<ipython-input-3-24946c882679> in <module>
----> 1 find_sqrt(-56)
<ipython-input-1-e201b0a49914> in find_sqrt(a)
5 raise TypeError("a must be numeric")
6 elif a < 0:
----> 7 raise TypeError("a should not be negative")
8 else:
9 print(math.sqrt(a))
find_sqrt(6)
2.449489742783178
What Is An Exception ?
Exception are errors that occur at runtime .
In other words , if our program encounters an abnormal situation during it’s execution it
raises an exception.
For example,the statement
a=10/0
A Sample Code
a=int(input("Enter first no:"))
b=int(input("Enter second no:"))
c=a/b
print("Div is",c)
d=a+b
print("Sum is",d)
----------------------------------------------------------------------
-----
ValueError Traceback (most recent call
last)
<ipython-input-10-8366b991657c> in <module>
1 a=int(input("Enter first no:"))
----> 2 b=int(input("Enter second no:"))
3 c=a/b
4 print("Div is",c)
5 d=a+b
As we can observe , in the second run the code generated exception because Python does
not know how to handle division by 0. Moreover it did not even calculated the sum of 10
and 0 which is possible
a=int(input("Enter first no:"))
b=int(input("Enter second no:"))
c=a/b
print("Div is",c)
d=a+b
print("Sum is",d)
In this case since it is not possible for Python to covert “2a” into an integer , so it generated
an exception . But the message it displays is too technical to understand
except ExceptionI:
If there is ExceptionI, then execute this block.
except ExceptionII:
If there is ExceptionII, then execute this block.
......................
else:
If there is no exception then execute this block.
#Example:
A try statement may have more than one except clause for different exceptions.But at most
one except clause will be executed
Also , we must remember that if we are handling parent and child exception classes in
except clause then the parent exception must appear after child exception , otherwise child
except will never get a chance to run
import math
try:
x=10/5
print(x)
ans=math.exp(3)
print(ans)
except ZeroDivisionError:
print("Division by 0 exception occurred!")
except ArithmeticError:
print("Numeric calculation failed!")
2.0
20.085536923187668
import math
try:
x=10/0
print(x)
ans=math.exp(20000)
print(ans)
except ZeroDivisionError:
print("Division by 0 exception occurred!")
except ArithmeticError:
print("Numeric calculation failed!")
import math
math.exp(20000)
----------------------------------------------------------------------
-----
OverflowError Traceback (most recent call
last)
<ipython-input-16-34b2787f9eac> in <module>
1 import math
----> 2 math.exp(20000)
import math
try:
x=10/5
print(x)
ans=math.exp(20000)
print(ans)
except ZeroDivisionError:
print("Division by 0 exception occurred!")
except ArithmeticError:
print("Numeric calculation failed!")
2.0
Numeric calculation failed!
import math
try:
x=10/5
print(x)
ans=math.exp(20000)
print(ans)
except ArithmeticError:
print("Numeric calculation failed!")
except ZeroDivisionError:
print("Division by 0 exception occurred!")
2.0
Numeric calculation failed!
import math
try:
x=10/0
print(x)
ans=math.exp(20000)
print(ans)
except ArithmeticError:
print("Numeric calculation failed!")
except ZeroDivisionError:
print("Division by 0 exception occurred!")
We can write the keyword except without any exception class name
also .
In this case for every exception this except clause will run .
The only problem will be that we will never know the type of exception
that has occurred!
try:
You do your operations here;
......................
except :
For every kind of exception this block will execute
Now we know how to handle exception, in this section we will learn how to access
exception object in exception handler code.
To access the exception object created by Python we can use the keyword as and assign it
to a variable.
Finally using that variable we can get the details of the exception
a=10
b='c'
d=a/b
print(d)
----------------------------------------------------------------------
-----
TypeError Traceback (most recent call
last)
<ipython-input-2-310ad5b1b85b> in <module>
1 a=10
2 b='c'
----> 3 d=a/b
4 print(d)
----------------------------------------------------------------------
-----
ValueError Traceback (most recent call
last)
<ipython-input-3-ea06110b60f0> in <module>
1 a=int(input("Input first no:"))
----> 2 b=int(input("Input second no:"))
3 c=a/b
4 print(c)
while(True):
try:
a=int(input("Input first no:"))
b=int(input("Input second no:"))
c=a/b
print("Div is ",c)
break;
except (ValueError,ZeroDivisionError) as e:
print(e)
Python allows us to get more details about the exception by calling the function exc_info().
Following are it’s important points:
It is available in the module sys
It returns a tuple containing 3 items called type, value and traceback
The variable type is the name of exception class, value is the instance of exception class and
traceback contains the complete trace of the exception
import sys
while(True):
try:
a=int(input("Input first no:"))
b=int(input("Input second no:"))
c=a/b
print("Div is ",c)
break;
except:
a,b,c=sys.exc_info()
print("Exception class:",a)
print("Exception message:",b)
print("Line number:",c.tb_lineno)
Sometimes , we need to print the details of the exception exactly like Python does .
We do this normally , when we are debugging our code.
The class traceback which is available in the module traceback helps us do this
import traceback
while(True):
try:
a=int(input("Input first no:"))
b=int(input("Input second no:"))
c=a/b
print("Div is ",c)
break;
except:
print(traceback.format_exc())
Raising An Exception
We can force Python to generate an Exception using the keyword raise.
This is normally done in those situations where we want Python to throw an exception in a
particular condition of our choice
Syntax: raise ExceptionClassName
raise ExceptionClassName( message )
Write a program to ask the user to input 2 integers and calculate and print their division.
Make sure your program behaves as follows:
If the user enters a non integer value then ask him to enter only integers If denominator is
0 , then ask him to input non-zero denominator If any of the numbers is negative then
display the message negative numbers not allowed Repeat the process until correct input is
given
Only if the inputs are correct then display their division and terminate the code
while(True):
a=int(input("please write a input:"))
if a>10:
break
print("please enter greater than 10")
while(True):
try:
a=int(input("Input first no:"))
b=int(input("Input second no:"))
if a<0 or b<0:
raise Exception("Negative numbers not allowed!Try
again")
c=a/b
print("Div is ",c)
break;
except ValueError:
print("Please input integers only! Try again")
except ZeroDivisionError:
print("Please input non-zero denominator")
except Exception as e:
print(e)
If we have a code which we want to run in all situations, then we should write it inside the
finally block.
Python will always run the instructions coded in the finally block.
It is the most common way of doing clean up tasks , like, closing a file or disconnecting with
the DB or logging out the user etc
The finally block has 2 syntaxes:
Syntax 1
try:
# some exception generating code
except :
# exception handling code
finally:
# code to be always executed
try:
# some exception generating code
finally:
# code to be always executed
while(True):
try:
a=int(input("Input first no:"))
b=int(input("Input second no:"))
c=a/b
print("Div is ",c)
break;
except ZeroDivisionError:
print("Denominator should not be zero")
finally:
print("Thank you for using the app!")
Python has many built-in exceptions which forces our program to output an error when
something in it goes wrong.
However, sometimes we may need to create our own exceptions which will be more
suitable for our purpose.
Such exceptions are called User Defined Exceptions
In Python, users can define such exceptions by creating a new class.
This exception class has to be derived, either directly or indirectly, from Exception class.
Most of the built-in exceptions are also derived form this class.
class NegativeNumberException(Exception):
def __init__(self):
print("please type a pos number")
while(True):
try:
a=int(input("Input first no:"))
b=int(input("Input second no:"))
if a<0 or b<0:
raise NegativeNumberException()
c=a/b
print("Div is ",c)
break;
except ValueError:
print("Please input integers only! Try again")
except ZeroDivisionError:
print("Please input non-zero denominator")
except NegativeNumberException as e:
print(e)
import math
ans=math.exp(20000)
----------------------------------------------------------------------
-----
OverflowError Traceback (most recent call
last)
<ipython-input-8-660e2d42fc5d> in <module>
1 import math
----> 2 ans=math.exp(20000)
ans
7.38905609893065