Exception handling in Python
Python provides features to handle any unexpected error in Python programs and to add debugging capabilities in them -
Exception Handling
Assertions
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
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)
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
A single try statement can have multiple asoociated except clauses(statements), in case it contains statements that may throw different types of exceptions
A generic except clause can be provided, which handles any exception
After the except clause(s), an else-clause can be included, whose code gets executed if the code in the try: block does not raise an exception
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
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
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
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
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
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
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'
Exceptions can be raised by using the raise
statement following by Exception object with optional arguments
raise Exception(*args)
Here, Exception is the type of exception (for example, ValueError)
The arguments args
are optional
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)
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
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
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
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 |