Python Exceptions

When a Python program encounters an error, it can stop the execution of the rest of the program. Errors in Python can be syntax errors or exceptions. This tutorial will explore what exceptions are, their differences from syntax errors, how to use try and except blocks, how to raise exceptions, make assertions, and provide an overview of built-in exceptions.

What is an Exception?

An exception in Python is an event that disrupts the normal flow of a program's execution. When Python code encounters a condition it cannot handle, it raises an exception. An exception is an object that describes an error.

When an exception is raised, you have two options: handle the exception immediately or allow the program to terminate.

Exceptions vs. Syntax Errors

Syntax errors occur when the Python interpreter identifies a problem with the code's syntax. For example:

# Python code with a syntax error
string = "Python Exceptions"
for s in string:
     if (s != o:
         print(s)

Output:

if (s != o:
             ^
SyntaxError: invalid syntax

The arrow indicates where the syntax error occurred (an unclosed parenthesis). After correcting the syntax error:

# Corrected Python code
string = "Python Exceptions"

for s in string:
    if (s != 'o'):
        print(s)

Output:

P
y
t
h
n
E
x
c
e
p
t
i
o
n
s

If a syntactically valid code produces an error, it’s typically an exception. For example, using an undefined variable:

# Python code with a NameError
string = "Python Exceptions"

for s in string:
    if (s != o):
        print(s)

Output:

NameError: name 'o' is not defined

Here, a NameError occurs because o is not defined.

Try and Except Statement - Catching Exceptions

In Python, you can catch and handle exceptions using try and except blocks. The try block contains code that might raise an exception, and the except block contains code that handles the exception.

# Python code to handle an exception using try and except

a = ["Python", "Exceptions", "try and except"]
try:
    # Looping through indices beyond the array length
    for i in range(4):
        print("The index and element from the array is", i, a[i])
except IndexError:
    print("Index out of range")

Output:

The index and element from the array is 0 Python
The index and element from the array is 1 Exceptions
The index and element from the array is 2 try and except
Index out of range

In this example, the try block attempts to access an index that is out of range, and the except block catches the IndexError and prints a message.

How to Raise an Exception

You can intentionally raise exceptions using the raise keyword. This is useful for enforcing certain conditions in your code.

# Python code to show how to raise an exception

num = [3, 4, 5, 7]
if len(num) > 3:
    raise Exception(f"Length of the given list must be less than or equal to 3 but is {len(num)}")

Output:

Exception: Length of the given list must be less than or equal to 3 but is 4

The raise statement stops the program and shows the custom exception message.

Assertions in Python

Assertions are used to verify conditions that must be true in your code. If an assertion fails, an AssertionError is raised.

# Python program to show how to use assert keyword

def square_root(number):
    assert (number >= 0), "The number must be non-negative"
    return number**(0.5)

# Calling function with valid and invalid values
print(square_root(36))
print(square_root(-36))

Output:

6.0
AssertionError: The number must be non-negative

The assertion checks if the input number is non-negative. If not, it raises an AssertionError.

Try with Else Clause

The else clause can be used with try and except. It executes only if no exceptions were raised in the try block.

# Python program to show how to use else clause with try and except clauses

def reciprocal(num1):
    try:
        reci = 1 / num1
    except ZeroDivisionError:
        print("We cannot divide by zero")
    else:
        print(reci)

# Calling the function with valid and invalid values
reciprocal(4)
reciprocal(0)

Output:

0.25
We cannot divide by zero

The else block executes when no ZeroDivisionError is encountered.

Finally Keyword in Python

The finally block is always executed, whether or not an exception was raised. It’s useful for cleanup actions.

# Python code to show the use of finally clause

try:
    div = 4 // 0
    print(div)
except ZeroDivisionError:
    print("Attempting to divide by zero")
finally:
    print('This is code in the finally block')

Output:

Attempting to divide by zero
This is code in the finally block

The finally block executes regardless of whether an exception occurred.

User-Defined Exceptions

You can define custom exceptions by inheriting from built-in exceptions.

class EmptyError(RuntimeError):
    def __init__(self, argument):
        self.argument = argument

var = " "
try:
    raise EmptyError("The variable is empty")
except EmptyError as e:
    print(e.argument)

Output:

The variable is empty

Here, EmptyError is a custom exception that inherits from RuntimeError.

Python Exceptions List

Here is a list of common built-in exceptions in Python:

Sr.No. Name of the Exception Description
1 Exception Base class for all exceptions.
2 StopIteration Raised by next() method of an iterator when no more items are available.
3 SystemExit Raised by sys.exit() to exit from Python.
4 StandardError Base class for all built-in exceptions except StopIteration and SystemExit.
5 ArithmeticError Base class for all numerical calculation errors.
6 OverflowError Raised when a calculation exceeds the maximum limit for a numeric type.
7 FloatingPointError Raised when a floating-point operation fails.
8 ZeroDivisionError Raised when a number is divided by zero.
9 AssertionError Raised when an assert statement fails.
10 AttributeError Raised when an attribute reference or assignment fails.
11 EOFError Raised when the end of a file is reached and no input is available.
12 ImportError Raised when an import statement fails.
13 KeyboardInterrupt Raised when the user interrupts program execution, usually with Ctrl+C.
14 LookupError Base class for all lookup errors.
15 IndexError Raised when a sequence index is out of range.
16 KeyError Raised when a dictionary key is not found.
17 NameError Raised when a local or global name is not found.
18 UnboundLocalError Raised when a local variable is referenced before assignment.
19 EnvironmentError Base class for all exceptions related to the environment.
20 IOError Raised for input/output operation failures.
21 SyntaxError Raised for syntax errors.
22 IndentationError Raised for incorrect indentation.
23 SystemExit Raised by sys.exit() method to exit Python.
24 TypeError Raised when an operation or function is applied to an object of inappropriate type.
25 ValueError Raised when an operation or function receives an argument of the right type but inappropriate value.
26 RuntimeError Raised for errors that occur during program execution.
27 NotImplementedError Raised when an abstract method that needs to be implemented is not defined.