Newby Coder header banner

Exception handling in Python

Python provides features to handle any unexpected error in Python programs and to add debugging capabilities in them -

What is an Exception?

An exception is an event, which occurs during execution of a program that disrupts normal flow of program's instructions

In Python, it is a Python object (a string, class or some other object) that represents an error

When an exception is raised by a code or program it has to be handled immediately, otherwise it terminates and quits after spitting out an error message

Handling an exception

If any code is present which can possibly raise an exception, the program can be prevented from being terminated by placing the suspicious code in a try: block

The try: block is to be followed by an except: block which handles the error (silently, if suitable, by using pass statement)

Syntax

simple syntax of try....except blocks :

try:
    suite of try statement which contains code which can raise exception(s)
except ExceptionI:
    If exception is of type ExceptionI, then this block is executed
except ExceptionII:
    If exception is ExceptionII, then this block is executed
except:
    Broad except statement, to handle any other type of exception 

Example

This example opens a file and writes content in file

#!/usr/bin/python
try:
    fh = open("example_file.txt","w")
    fh.write("some text content for file")
except IOError:
    print ("Error: Unable to open or read file")
else:
    print ("Content written in the file")
    fh.close() 

This produces following output

Content written in the file 

However, if the user does not have write permission, it raises an exception and prints the error

Error: Unable to open or read file 

Generic except clause with No Exceptions

An except statement can also be used without any exceptions defined:

try:
    statement(s) which might throw exception(s)
except:
    statement(s) to execute in case of any exception thrown
else:
    statement(s) to execute in case no exception is thrown 

This kind of a try-except statement catches all exceptions that might occur

Using this kind of try-except statement is not considered a good programming practice, since there might be lack of data to identify the root cause

except clause with Multiple Exceptions

An except statement can be used to handle multiple exceptions as follows -

try:
    statement(s) which might throw exception(s)
except(Exception1[,Exception2[,...ExceptionN]]]):
    statement(s) to execute in case of any exception from the provided Exceptions is thrown 

Python finally Clause

The finally block allows to provide code that is to be always executed after a try block, even if an exception is raised

A try-finally statement looks like

try:
    statement(s) which might throw exception(s)
    statement(s) which donot get executed in the event of an Exception
finally:
    statement(s) to be always executed, regardless of any Exception  

An except statement can also be present

try:
    statement(s) which might throw exception(s)
    statement(s) which donot get executed in the event of an Exception
except:
    statement(s) to be executed in the event of an exception
finally:
    statement(s) to be always executed, regardless of any Exception  
else clause cannot be used along with a finally clause

Example

A finally block can be used for closing a file after attempting to write on it

#!/usr/bin/python
try:
    fh = open("example_file.txt","w")
    try:
        fh.write("some text content for file")
    finally:
        fh.close()
        print("File closed")
except IOError:
    print("Error: Unable to read or open file") 

When an exception is thrown in the nested try block, execution passes to the finally block

After statements of finally block are executed, exception which was raised is handled in the except block of the outer try-except statement

Object of an Exception

To get additional information about an exception, it's object can be used

An exception can be captured as an object by using the as (alias) keyword along with a variable as follows:

try:
    statement(s)
except ExceptionType as e:
    statement to print or log e 

(e above) This variable receives the object of the specific exception raised

If multiple exceptions are handled in an except statement, then a variable follows the tuple of exceptions

The same can be obtained by using exc_info() method of sys module

import sys
try:
    statement(s)
except Exception:
    e = sys.exc_info()[0]
    statement to print or log e 

Example

Following is an example for a single exception

#!/usr/bin/python
def convert(var):
    try:
        return int(var)
    except ValueError as arg:
        print("invalid argument for a number:\n", arg)

convert("zzz") 

This produces following output

invalid argument for a number:
 invalid literal for int() with base 10: 'zzz' 

Raising an Exception

Exceptions can be raised by using the raise statement following by Exception object with optional arguments

Syntax

raise Exception(*args) 

Here, Exception is the type of exception (for example, ValueError)

The arguments args are optional

Example

An exception must be an object or class derived from BaseException

Following example raises an exception when input is None or empty

def raiser(question):
    if question is None or len(question) <1:
        raise ValueError("No question provided")
    else:
        raise ValueError("Lets raise the question")  

In order to catch an exception, an except clause must refer to the same exception thrown or a more generic exception (from which the current exception is derived)

User-Defined Exceptions

Python allows to create custom exceptions by deriving classes from the standard built-in exceptions

Here, a class is created that is subclassed from RuntimeError

class TakeaBreakError(RuntimeError):
    pass 

Once defined, it can be raised and caught as follows -

try:
    raise TakeaBreakError("That's enough code for today")
except TakeaBreakError as e:
    print(e) 

The variable e is used to access an instance of class TakeaBreakError which is caught

Assertions in Python

An assertion is a sanity-check, preferably used during testing a program

An Assertion evaluates an expression, and raises an exception if it returns false

Assertions are carried out by the assert statement

Assertions are often placed at the start of a function to check for valid input, and after a function call to check for valid output

assert Statement

Python evaluates the accompanying expression of an assert statement and raises an AssertionError exception if the expression is false

The syntax for assert is :

assert Expression[, Arguments] 

AssertionError exceptions can be caught and handled like any other exception using a try-except statement, but if not handled, they terminate the program and produce a traceback

Example

Here is a function that returns the percentage of a number out of another number, from(and excluding) 0 to 100

It uses assert statements to check if denominator and numerator are greater than 0 and numerator is less than or equal to denominator

#!/usr/bin/python
def percentage(num, denominator):
    num = float(num); denominator = float(denominator) #conversion to float so that it works in cases of string input
    assert(denominator > 0 ), "Error: denominator not greater than 0"
    assert(num > 0 and num <= denominator), "Error: invalid numerator"
    return num/denominator * 100

print("163.3/164 =", percentage("64.3", 65),"%")
print("31/0 =", percentage(31, 0),"%") 

When above code is executed, it produces following output

163.3/164 = 98.92307692307692 %
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in percentage
AssertionError: Error: denominator not greater than 0 

Standard Exceptions

List of Standard Exceptions -

Sr.No Exception Name Description
1

Exception

Base class for all exceptions

2

StopIteration

Raised when the next() method of an iterator does not point to any object

3

SystemExit

Raised by the sys

exit() function

4

StandardError

Base class for all built-in exceptions except StopIteration and SystemExit

5

ArithmeticError

Base class for all errors that occur for numeric calculation

6

OverflowError

Raised when a calculation exceeds maximum limit for a numeric type

7

FloatingPointError

Raised when a floating point calculation fails

8

ZeroDivisionError

Raised when division or modulo by zero takes place for all numeric types

9

AssertionError

Raised in case of failure of the Assert statement

10

AttributeError

Raised in case of failure of attribute reference or assignment

11

EOFError

Raised when there is no input from either the raw_input() or input() function and the end of file is reached

12

ImportError

Raised when an import statement fails

13

KeyboardInterrupt

Raised when the user interrupts program execution, usually by pressing Ctrl+c

14

LookupError

Base class for all lookup errors

15

IndexError

Raised when an index is not found in a sequence

16

KeyError

Raised when the specified key is not found in the dictionary

17

NameError

Raised when an identifier is not found in the local or global namespace

18

UnboundLocalError

Raised when trying to access a local variable in a function or method but no value has been assigned to it

19

EnvironmentError

Base class for all exceptions that occur outside the Python environment

20

IOError

Raised when an input/ output operation fails, such as the print statement or the open() function when trying to open a file that does not exist

21

IOError

Raised for operating system-related errors

22

SyntaxError

Raised when there is an error in Python syntax

23

IndentationError

Raised when indentation is not specified properly

24

SystemError

Raised when the interpreter finds an internal problem, but when this error is encountered the Python interpreter does not exit

25

SystemExit

Raised when Python interpreter is quit by using the sys

exit() function

If not handled in the code, causes the interpreter to exit

26

TypeError

Raised when an operation or function is attempted that is invalid for the specified data type

27

ValueError

Raised when the built-in function for a data type has the valid type of arguments, but the arguments have invalid values specified

28

RuntimeError

Raised when a generated error does not fall into any category

29

NotImplementedError

Raised when an abstract method that needs to be implemented in an inherited class is not actually implemented