0% found this document useful (0 votes)
34 views26 pages

CH 7-1

Chapter 7 discusses exceptions in Python, categorizing errors into syntax errors and logical errors (exceptions). Syntax errors occur due to incorrect code structure, while logical errors arise during execution and can lead to runtime errors if not handled properly. The chapter emphasizes the importance of exception handling using try and except blocks to maintain program stability.

Uploaded by

jiveshpal001
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views26 pages

CH 7-1

Chapter 7 discusses exceptions in Python, categorizing errors into syntax errors and logical errors (exceptions). Syntax errors occur due to incorrect code structure, while logical errors arise during execution and can lead to runtime errors if not handled properly. The chapter emphasizes the importance of exception handling using try and except blocks to maintain program stability.

Uploaded by

jiveshpal001
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

Chapter 7: - Exceptions

1. Errors
Errors are problems that occur in the program due to an illegal operation performed by the user
or by the fault of a programmer, which halts the normal flow of the program. Errors are also
termed bugs or faults. There are mainly two types of errors in python programming. Let us learn
about both types of python errors:

1. Syntax errors
2. Logical Errors or Exceptions

Whenever we do not write the proper syntax of the python programming language (or any other
language) then the python interpreter throws an error known as a syntax error.

On the other hand, Logical Errors are those errors that cannot be caught during compilation time.
As we cannot check these errors during compile time, we name them Exceptions. Exceptions can
cause some serious issues so we should handle them effectively.

Note: Syntax errors can also be called Compile Time Error. Some of the most common compile-
time errors are syntax errors, library references, incorrect import of library functions and
methods, uneven bracket pair(s), etc.

Syntax Errors

A syntax error is one of the most basic types of error in programming. Whenever we do not write
the proper syntax of the python programming language (or any other language) then the python
interpreter or parser throws an error known as a syntax error. The syntax error simply means that
the python parser is unable to understand a line of code.

Let us take an example to understand the syntax error better.

number = 100

if number > 50
print("Number is greater than 50!")

Output:

File "test.py", line 3


if number > 50
^
SyntaxError: invalid syntax
As we can see in the example above, the python interpretation raised a syntax error
saying invalid syntax. Since we have missed the semicolon (:) after the if statement so that's why
the python interpreter raised a syntax error.

Some of the general syntax errors can be typing errors (errors), incorrect indentation, or incorrect
arguments. In case of syntax errors, we should look at our code and try to understand the
problem.

Note: In various IDEs (Integrated Development Environment), the syntax error(s) are shown by
red dashed lines.

Logical Errors

As we have seen above there are two main types of python errors. We already have studied the
syntax error, let us now learn about the logical errors in python.

Logical Errors are those errors that cannot be caught during compilation time. As we cannot
check these errors during compile time, we name them Exceptions. Since we cannot check the
logical errors during compilation time, it is difficult to find them.

There is one more name of logical error. Run time errors are those errors that cannot be caught
during compilation time. So, run-time can cause some serious issues so we should handle them
effectively.

Let us now talk about some of the most common logical types of errors in python programming.

ZeroDivisionError Exception

ZeroDivisionError is raised by the Python interpreter when we try to divide any number by zero.
Let us take an example to understand the ZeroDivisionError.

number = 100
divided_by_zero = number / 0

print(divided_by_zero)

Output:

Traceback (most recent call last):


File "d:\test.py", line 2, in <module>
divided_by_zero = number / 0
ZeroDivisionError: division by zero
Indentation is not Correct

The Indentation error is another type of error in python that can be summed up inside the syntax
error. As we know, we use indentation to define a block of code in python. So, in case of
improper indentation, the Python interpreter raises an Indentation error. Let us take an example
to understand the Indentation Error.

number = 57

if number == 57:
print(57)

Output:

File "d:\test.py", line 4


print(57)
^
IndentationError: expected an indented block
Built-in Exceptions

Like any other programming language, Python has some built-in exceptions.

Note: All instances in Python must be instances of a class that derives from BaseException.

Let us learn about the common built-in exceptions in python.

Exception Description

As the name suggests, the IndexError is raised when the wrong index of
IndexError
a list is used.

AssertionError AssertionError is raised when the assert statement fails

AttributeError AttributeError is raised when an attribute assignment is failed.

ImportError is raised when an imported module is not found or there is


ImportError
a problem in importing the required module.

KeyError KeyError is raised when the key of the dictionary is not found.

NameError NameError is raised when the variable is not yet defined.

MemoryError MemoryError is raised when a program runs out of memory.

TypeError is raised when a function or an operation is applied in an


TypeError
incorrect type.

EOFError is raised when the input() function hits the condition of end-
EOFError
of-file.

FloatingPointError FloatingPointError is raised when a floating-point operation fails.

GeneratorExit TypeError is raised when we call the generator's close() method.


Exception Description

KeyboardInterrupt is raised when a user hits the interrupt key


KeyboardInterrupt
i.e. Ctrl+C or Delete.

NotImplementedError is raised by abstract methods when they are


NotImplementedError
defined.

OSError OSError is raised when system operation causes system-related errors.

OverflowError is raised when the result of an arithmetic operation is too


OverflowError
large.

ReferenceError is raised when a weak reference proxy is used to access


ReferenceError
a garbage collected referent.

RuntimeError is raised when an error does not fall under any other
RuntimeError
category of built-in Python exceptions.

StopIteration is raised by the iterator's next() function to indicate that


StopIteration
there is no further item to be returned by the iterator.

IndentationError IndentationError is raised when there is incorrect indentation.

TabError TabError is raised when interpreter detects internal error.

SystemError is raised when indentation consists of inconsistent tabs and


SystemError
spaces.

UnboundLocalError is raised when a reference is made to a local


UnboundLocalError variable in a function or method, having no value bound to that
variable.

UnicodeError is raised when a Unicode-related encoding or decoding


UnicodeError
error occurs.

UnicodeEncodeError is raised when a Unicode-related error occurs at


UnicodeEncodeError
the time of encoding.

UnicodeDecodeError is raised when a Unicode-related error occurs at


UnicodeDecodeError
the time of decoding.

UnicodeTranslateError is raised when a Unicode-related error occurs


UnicodeTranslateError
during translating.

ValueError is raised when a function is given the correct type of


ValueError
argument but with an improper value.

ZeroDivisionError ZeroDivisionError is raised when we try to divide any number by zero.


Errors are problems that occur in the program due to an illegal operation
performed by the user or by the fault of a programmer. Exception Handling is the
process of handling errors and exceptions such that the normal execution of the
system is not halted. Exception handling is required to prevent the program from
terminating abruptly.

• Errors are the problems that occur in the program due to an illegal operation
performed by the user or by the fault of a programmer, which halts the normal flow of
the program.
• Errors are also termed bugs or faults. There are mainly two types of errors in python
programming namely - Syntax errors and Logical Errors or Exceptions.
• Whenever we do not write the proper syntax of the python programming language (or
any other language) then the python interpreter throws an error known as syntax
error.
• Syntax errors can also be called Compile Time Error. Some of the most common
compile-time errors are syntax errors, library references, incorrect import of library
functions and methods, uneven bracket pair(s), etc.
• Logical Errors are those errors that cannot be caught during compilation time. As we
cannot check these errors during compile time, we name them Exceptions.
• Exception Handling is the process of handling errors and exceptions such that the
normal execution of the system is not halted.

2. Runtime Errors
• A runtime error in a program is one that occurs after the program has
been successfully compiled.
• The Python interpreter will run a program if it is syntactically correct (free
of syntax errors). However, if the program encounters a runtime error - a
problem that was not detected when the program was parsed and is only
revealed when a specific line is executed - it may exit unexpectedly
during execution. When a program crashes due to a runtime error, we say
it has crashed
Some examples of Python Runtime errors
• division by zero
• performing an operation on incompatible types
• using an identifier that has not been defined
• accessing a list element, dictionary value, or object attribute which
doesn’t exist
• trying to access a file that doesn’t exist
Let's take a closer look at each of them by using an example

Division by zero
If we divide any number by zero, we get this error.

Algorithm (Steps)
Following are the Algorithm/steps to be followed to perform the desired task −
• Take a variable to store the first input number.
• Take another variable to store the second input number(Here the second
number should be 0).
• Divide the first number by the second number and print the result.
Example
The following program returns the runtime error if we divide a number with zero −

# First Input Number

firstNumb = 11

# Second Input Number (Here it is 0)

secondNumb = 0

# Dividing the first Number by the second Number

print(firstNumb/secondNumb)

Output
On executing, the above program will generate the following output −
Traceback (most recent call last):
File "main.py", line 6, in <module>
print(firstNumb/secondNumb)
ZeroDivisionError: division by zero
Because the second number is 0 and no number can be divided by 0, we get a runtime
error.

Performing an operation on incompatible types


This error occurs when we perform operations like addition, multiplication, and so on
on incompatible data types.
Algorithm (Steps)
Following are the Algorithm/steps to be followed to perform the desired task −
• Take a string and assign some random value to it and store it in a variable.
• Take an integer and assign some random integer value to it and store it in
another variable.
• Perform some operations such as addition on the above variables and
print it.
Example
The following program returns the runtime error if we perform operation on
incompatible data types −

# Input string

inputString = "TutorialsPoint"

# Input Number

inputNumber = 11

# Adding both integer and string values

print(inputString + inputNumber)

Output
On executing, the above program will generate the following output −
Traceback (most recent call last):
File "main.py", line 6, in <module>
print(inputString + inputNumber)
TypeError: must be str, not int
We can't add an integer to the string data type here, so we get a type error (runtime
error).

Using an identifier that has not been defined


This error occurs when we attempt to access an identifier that has not been declared
previously.

Example
The following program returns the runtime error if we are using undefined identifier −

# Printing undefined identifier


print(tutorialsPoint)

Output
On executing, the above program will generate the following output −
Traceback (most recent call last):
File "main.py", line 2, in <module>
print(tutorialsPoint)
NameError: name 'tutorialsPoint' is not defined
Because we did not define the tutorialsPoint identifier and are accessing it by printing
it, a runtime error occurs (Name error).

Accessing a list element, dictionary value, or object


attribute which doesn’t exist
This runtime error occurs when we attempt to access a non-existent
list,string,dictionary element/index.
When we attempt to use an index that does not exist or is too large, it throws
an IndexError.

Algorithm (Steps)
Following are the Algorithm/steps to be followed to perform the desired task −
• Create a list and assign some random values to it.
• Access the list element by index by giving the index that doesn’t exist and
printing it.
Example
The following program returns the index error if we access an element out of range −

# input list

inputList =[1, 4, 8, 6, 2]

# printing the element at index 10 of an input list

# throws an IndexError as the index 10 doesn't exist in the input list

print("Element at index 10:", inputList[10])

Output
On executing, the above program will generate the following output −
Traceback (most recent call last):
File "main.py", line 6, in <module>
print("Element at index 10:", inputList[10])
IndexError: list index out of range
There are 5 elements in the list, and we are attempting to access the 10th index,
which does not exist, resulting in an index error.

Trying to access a file that doesn’t exist


If we try to open a file that doesn't exist, it throws a runtime error.

Algorithm (Steps)
Following are the Algorithm/steps to be followed to perform the desired task −
• Create a variable to store the path of the text file. This is a fixed value. In
the example below, this value must be substituted with the file path from
your own system.
• Use the open() function(opens a file and returns a file object as a result)
to open the text file in read-only mode by passing the file name, and
mode as arguments to it (Here “r” represents read-only mode)
givenFile = open(inputFile,"r")
• Print it value of the given file.
Example
The following program returns the file not found error if we access an file that doesn’t
exist −

# input file path

inputFile = "tutorialsPoint.txt"

# Opening the given file in read-only mode.

givenFile = open(inputFile,"r")

# Printing value of given File

print(givenFile)

Output
On executing, the above program will generate the following output −
Traceback (most recent call last):
File "main.py", line 4, in <module>
givenFile = open(inputFile,"r")
FileNotFoundError: [Errno 2] No such file or directory: 'tutorialsPoint.txt'

3. The Exception Model


Exceptions are errors that are detected during execution. Whenever there is an error in a
program, exceptions are raised.

If these exceptions are not handled, it drives the program into a halt state. Exception
handling in python is required to prevent the program from terminating abruptly. This article
will further explain Exception Handling in Python.

An exception is a class in Python that represents an error. When an exception is raised during the
execution of code, it disrupts the normal flow of the program and can lead to a halt state or even
a crash. To avoid this, it's important to do Exception handling in Python in a way that allows the
program to continue running even if an error occurs.

Exception handling in Python is achieved using the try and except blocks. The try block is used
to enclose the code that may raise an exception, while the except block is used to handle the
exception that may occur. If an exception is raised in the try block, the program jumps to the
except block to handle it, instead of halting the program altogether.

The basic syntax of a try-except block in Python is as follows:

try:
# code that may raise an exception
except:
# code to handle the exception

It's important to note that try and except blocks must be used together in order to handle
exceptions properly. Writing just try or except blocks alone will result in an error.In addition, the
except block can specify the type of exception that it wants to catch.

Common Exceptions in Python

Before proceeding further, we need to understand what some of the common exceptions that
python throws are.

All the inbuilt exceptions in python are inherited from the common ‘Exception’ class. Some of
the common inbuilt exceptions are:

Exception Name Description


Exception Name Description

Exception All exceptions inherit this class as the base class for all exceptions.

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

StandardError All exceptions inherit this class except stop StopIteration and SystemExit

ArithmeticError Errors that occur during numeric calculation are inherited by it.

When a calculation exceeds the max limit for a specific numeric data
OverflowError
type

ZeroDivisionError Raised when division or modulo by zero takes place.

AssertionError Raised when an assert statement fails

AttributeError Raised in case of failure of attribute assignment

Raised when the end of file is reached, usually occurs when there is no
EOFError
input from input() function

ImportError Raised when an import statement fails

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


NameError
scope.

SyntaxError Raised when there is an error in python syntax.

IndentationError Raised when indentation is not proper

Raised when a specific operation of a function is triggered for an invalid


TypeError
data type

Raised when invalid values are provided to the arguments of some


ValueError
builtIn function for a data type that has a valid type of arguments.

RuntimeError Raised when an error does not fall into any other category

Raised when an abstract method that needs to be implemented in an


NotImplementedError
inherited class is not actually implemented.

These are just some of the common exceptions in python. To understand more on types of
exceptions check python’s official documentation on exceptions

Catching Specific Exceptions in Python

In the above example, we caught the exception that was being raised in the try block, but the
except blocks are going to catch all the exceptions that try might raise.
Well, it’s considered a good practice to catch specific types of exceptions and handle them
accordingly. And yes, try can have multiple except blocks. We can also use a tuple of values in
an except to receive multiple specific exception types.

Let’s take an example to understand this more deeply:

def divideNos(a, b):


return a/b # An exception might raise here if b is 0 (ZeroDivisionError)
try:
a = input('enter a:')
b = input('enter b:')
print('after division', divideNos(a, b))
a = [1, 2, 3]
print(a[3]) # An exception will raise here as size of array ‘a’ is 3 hence
is accessible only up until 2nd index

# if IndexError exception is raised


except IndexError:
print('index error')
# if ZeroDivisionError exception is raised
except ZeroDivisionError:
print('zero division error')

Output:

enter a:4
enter b:2
after division 2.0
index error

• In the above code the exceptions raised totally depend upon the input that the user might enter.
Hence if a user enters a value as 0 for ‘b’, the python interpreter will raise a ZeroDivisionError.
• And as the array ‘a’ has a length of 3, and the user is trying to access an element at index 3,
an IndexError will be raised by the python interpreter.
• Each except block has been defined for both the exceptions as one of them receives exceptions
of type IndexError and the other receives of type ZeroDivisionError.

If we want the above snippet to catch exception for both IndexError OR ZeroDivisionError, it
can be re-written as:

def divideNos(a, b):


return a/b
try:
a = int(input('enter a:'))
b = int(input('enter b:'))
print('after division', divideNos(a,b))
a = [1, 2, 3]
print(a[3])
except (IndexError, ZeroDivisionError):
print('index error OR zero division error')

Output:
enter a:10
enter b:2
after division 5.0
index error OR zero division error

Note: Only one of the except blocks is triggered when an exception is raised. Consider an
example where we have one except as except IndexError and another as except(IndexError,
ZeroDivisionError) then the one written first will trigger.

Raising Custom Exceptions

Even though exceptions in python are automatically raised in runtime when some error occurs.
Custom and predefined exceptions can also be thrown manually by raising it for specific
conditions or a scenario using the raise keyword. (A custom exception is an exception that a
programmer might raise if they have a requirement to break the flow of code in some specific
scenario or condition) String messages supporting the reasons for raising an exception can also
be provided to these custom exceptions.

Syntax to Raise an Exception


try:
# on some specific condition or otherwise
raise SomeError(OptionalMsg)
Except SomeError as e:
# Executed if we get an error in the try block
# Handle exception ‘e’ accordingly

For example:

def isStringEmpty(a):
if(type(a)!=str):
raise TypeError('a has to be string')
if(not a):
raise ValueError('a cannot be null')
a.strip()
if(a == ''):
return False
return True

try:
a = 123
print('isStringEmpty:', isStringEmpty(a))
except ValueError as e:
print('ValueError raised:', e)

except TypeError as e:
print('TypeError raised:', e)

Output:

TypeError raised: a has to be string


• In the above code, the variable ‘a’ can hold whatever value that is assigned to it. Here we assign
it a number and we’re passing to a custom method isStringEmpty that checks if a string is an
empty string.
• But we orchestrated it to throw a TypeError, by assigning ‘a’ variable a number.
• In the method, we’re checking if the variable is a string or not and if it holds a value or not. In
this case, it is supposed to be a string, but assigned it as a number as we’re raising an exception
by using

try except and ELSE!

Sometimes you might have a use case where you want to run some specific code only when there
are no exceptions. For such scenarios, the else keyword can be used with the try block. Note that
this else keyword and its block are optional.

Syntax With Else Clause


try:
# on some specific condition or otherwise
raise SomeError(OptionalMsg)
except SomeError as e:
# Executed if we get an error in the try block
# Handle exception ‘e’ accordingly
else
# Executed if no exceptions are raised

Example:

When an exception is not raised, it flows into the optional else block.

try:
b = 10
c = 2
a = b/c
print(a)
except:
print('Exception raised')
else:
print('no exceptions raised')

Output:

5.0
no exceptions raised

In the above code, As both the inputs are greater than 0 which is not a risk
to DivideByZeroException, hence try block won’t raise any exception and hence ‘except’ block
won’t be triggered. And only when the control doesn’t flow to the except block, it flows to
the else block. Further handling can be done inside this else block if there is something you want
to do.

Example:
When an exception is raised, control flows into the except block and not the else block.

try:
b = 10
c = 0
a = b/c
print(a)
except Exception as e:
print('Exception raised:', e)
else:
print('no exceptions raised')

Output:

Exception raised: division by zero

In the above code, As both the ‘b’ input is 0 which is a risk to DivideByZeroException, hence
the ‘try’ block will raise an exception, and hence the ‘except’ block will be triggered. And now
as there is an exception raised, the control flows to the except block and not to the else block.

Try Clause with Finally

Finally is a keyword that is used along with try and except, when we have a piece of code that is
to be run irrespective of if try raises an exception or not. Code inside finally will always run after
try and catch.

Example:

Where an exception is raised in the try block and except is triggered.

try:
temp = [1, 2, 3]
temp[4]
except Exception as e:
print('in exception block: ', e)
else:
print('in else block')
finally:
print('in finally block')

Output:

in exception block: list index out of range


in finally block

In the above code, we’re creating an array with 3 elements, i.e. max index up till 2. But when we
try to access the 4th index, it will raise an exception of index out of range and will be caught in
the except block. But here we need to observe that the finally block has also been triggered.

Example:
Rewriting the above code such that exception is not raised. Where an exception is not raised and
else and finally both are triggered.

Note: else block will always be triggered before finally and finally will always trigger
irrespective of any exceptions raised or not.

try:
temp = [1, 2, 3]
temp[1]
except Exception as e:
print('in exception block: ', e)
else:
print('in else block')
finally:
print('in finally block')

Output:

in else block
in finally block

In the above code, we’re creating an array with 3 elements, i.e. max index up till 2. But when we
try to access the 2nd index, now it will not raise an exception and control will now flow to
another block and then to finally.

But here we need to observe that the finally block has also been triggered even though the
exception was not raised.

Why Use Finally or Else in try..except?


def Checkout(itemsInCart):
try:
id = GetOrderIdForBooking() # Always creates an order before booking
items
BookItems(itemsInCart) # assuming this method raises an exception while
booking one of the items
except Exception as e:
LogErrorOccuredWhileBooking(e) # Log failed booking
else:
LogSuccessfulBookingStatus(id) # Log successful booking
finally:
EmailOrderStatusToUser(id) # Either ways send order email to user

itemsInCart = ['mobile', 'earphones', 'charger'] # assume user has these


items in their cart
Checkout(itemsInCart) # checking out items the user has in their cart.

• Consider above as a pseudo-code to a program where it checks out items added by the user in
their cart.
• The Checkout method always creates an order id before booking all the items in the cart.
• Assuming itemsInCart contains all the items the user has added to a cart.
• In the checkout experience of an e-commerce website, an orderId is created irrespective of
whether a booking of all items has been a success, failed, or partially failed.

• Hence in the above pseudo-code, we’re creating an orderId using GetOrderIdForBooking() and
assume it returns a random string for each order. BookItems() books all the items for us in
the itemsInCart array.

• If some error occurs while booking items, we have to log the reason for the
exception LogErrorOccuredWhileBooking() does that job for us and if it's successful we have to
log that the booking was successful.
• Now whatever the status of the order is, either way we have to email the status of the order to
the user and that’s what the EmailOrderStatus() does for us.

The above example perfectly fits for an application of try, except or else and finally block as
each block is playing a role that might’ve been difficult to achieve if we didn’t use these blocks.

What Happens if Errors are Raised in Except or Finally Block?


try:
SomeFunction() # assuming it throws some error
except exception as e:
Log(e) # assuming some exception occurred again while logging this
exception
finally:
# This will still execute even after an error was raised inside catch block
& gives you a final chance to handle the situation your way

• If an error occurs while handling something in an except block, the finally block still gives us a
chance to handle the situation our way.
Note: Once an exception/error is raised in the except block, finally block is triggered but the
program still goes into a halt state post to that and the flow is broken.
• But what if an error occurs in the finally block? Let’s orchestrate these series of events in the
following code:

try:
raise Exception("message from try block")
except Exception as e:
print('in except block:', e)
raise Exception("exception raised in except block")
finally:
print("in finally")
raise Exception("exception raised in finally block")

Output:

in except block: message from try block


in finally
Traceback (most recent call last):
File "<string>", line 2, in <module>
Exception: message from try block
During handling of the above exception, another exception occurred:

Traceback (most recent call last):


File "<string>", line 5, in <module>
Exception: exception raised in except block

During handling of the above exception, another exception occurred:

Traceback (most recent call last):


File "<string>", line 8, in <module>
Exception: exception raised in finally block

• Well, the finally block won’t be completed beyond the point where the exception is thrown.
Note that except block won’t be triggered again.

Conclusion

• Exceptions can be expected or unexpected either way they are to be handled as the application
goes into a halt state that most of the applications cannot afford
• Any code that is prone to an exception must be written in try block, if an exception is raised then
the control goes into the except block - provided the except block accepts that specific type of
exception or all exceptions in general.
• If no exception is raised then the code flows to the else block which is optional. Whether an
exception is raised or not control always flows to the finally block which is also optional.

• Syntax in a nutshell:
try:
# Some Code
except:
# Executed if an error is raised by the try block
# Handle exception here
else:
# OPTIONAL & Executed if no exceptions are raised
finally:
# OPTIONAL & will always be executed in the end

• Handling exceptions is an important part of any application development as it enhances the


quality of your end product.
4. Exception Hierarchy

1. BaseException:

• Typically, you wouldn't handle this exception directly because it's very broad and could
encompass system-exiting exceptions like SystemExit, KeyboardInterrupt, etc.

2. Exception:

• This is a general-purpose exception that catches most built-in exceptions. You might use
it when you want to handle any unexpected error.

try:

# Some code that may raise an exception

result = 10 / 0 # This will raise a ZeroDivisionError

except Exception as e:

print(f"An error occurred: {e}")

3. ArithmeticError:

• Here's an example of ZeroDivisionError, a subclass of ArithmeticError:


try:

result = 10 / 0

except ZeroDivisionError:

print("Error: Division by zero!")

4. LookupError:

• Example with IndexError:

my_list = [1, 2, 3]

try:

print(my_list[4]) # Trying to access an index that doesn't exist

except IndexError:

print("Error: Index out of range!")

5. AssertionError:

• Example using assert:

x = 10

try:

assert x == 5 # This will raise an AssertionError because x is not 5

except AssertionError:

print("Error: Assertion failed!")

6. AttributeError:

• Example accessing a non-existent attribute:

class MyClass:

pass

obj = MyClass()

try:

print(obj.attribute) # 'attribute' attribute does not exist

except AttributeError:

print("Error: Attribute does not exist!")


7. EOFError:

• Example reading from input():

try:

user_input = input("Enter something: ")

except EOFError:

print("Error: End of file reached!")

8. ImportError:

• Example trying to import a non-existent module:

try:

import non_existent_module

except ImportError:

print("Error: Module not found!")

9. NameError:

• Example accessing an undefined variable:

try:

print(undefined_variable)

except NameError:

print("Error: Variable is not defined!")

10. TypeError:

• Example of using unsupported operation on different data types:

try:

result = "10" / 2 # This will raise a TypeError

except TypeError:

print("Error: Unsupported operation!")

And so on for other exceptions in the hierarchy. These examples demonstrate how different exceptions
can occur in various scenarios and how you can handle them using try and except blocks.
5. Handling Multiple Exceptions
Given a piece of code that can throw any of several different exceptions, and
one needs to account for all of the potential exceptions that could be raised
without creating duplicate code or long, meandering code passages.
If you can handle different exceptions all using a single block of code, they can
be grouped together in a tuple as shown in the code given below :
Code #1 :

try:
client_obj.get_url(url)
except (URLError, ValueError, SocketTimeout):
client_obj.remove_url(url)

The remove_url() method will be called if any of the listed exceptions occurs.
If, on the other hand, if one of the exceptions has to be handled differently,
then put it into its own except clause as shown in the code given below :
Code #2 :

try:
client_obj.get_url(url)
except (URLError, ValueError):
client_obj.remove_url(url)
except SocketTimeout:
client_obj.handle_url_timeout(url)

Many exceptions are grouped into an inheritance hierarchy. For such


exceptions, all of the exceptions can be caught by simply specifying a base
class. For example, instead of writing code as shown in the code given below –
Code #3 :

try:
f = open(filename)
except (FileNotFoundError, PermissionError):
...

Except statement can be re-written as in the code given below. This works
because OSError is a base class that’s common to both
the FileNotFoundError and PermissionError exceptions.
Code #4 :
try:
f = open(filename)
except OSError:
...

Although it’s not specific to handle multiple exceptions per se, it is worth
noting that one can get a handle to the thrown exception using them as a
keyword as shown in the code given below.
Code #5 :

try:
f = open(filename)

except OSError as e:
if e.errno == errno.ENOENT:
logger.error('File not found')
elif e.errno == errno.EACCES:
logger.error('Permission denied')
else:
logger.error('Unexpected error: % d', e.errno)

The e variable holds an instance of the raised OSError. This is useful if the
exception has to be invested further, such as processing it based on the value
of the additional status code. The except clauses are checked in the order
listed and the first match executes.
Code #6 : Create situations where multiple except clauses might match

f = open('missing')

Output :
Traceback (most recent call last):
File "", line 1, in
FileNotFoundError: [Errno 2] No such file or directory: 'miss

try:
f = open('missing')
except OSError:
print('It failed')
except FileNotFoundError:
print('File not found')
Output :
Failed
Here the except FileNotFoundError clause doesn’t execute because
the OSError is more general, matches the FileNotFoundError exception, and
was listed first.

6. Raise
In Python, the raise statement is used to explicitly raise an exception or error. This can
be done to handle exceptional situations in your code, such as when a condition occurs
that warrants an error being reported.

Here's the basic syntax of the raise statement:


raise exception_class("Optional error message")

Where:

• “exception_class” is the type of exception to be raised.

• "Optional error message" is an optional string providing additional information


about the exception.

For example, you might raise a “ValueError” when a function receives an invalid
argument:
def divide(x, y):

if y == 0:

raise ValueError("Cannot divide by zero")

return x / y

try:

result = divide(10, 0)

except ValueError as e:

print(f"An error occurred: {e}")

In this example, if the divisor y is 0, the raise statement is triggered, raising a ValueError
with the specified error message. Then, the exception is caught in the except block, and
the error message is printed.
You can also raise custom exceptions by defining your own exception classes. This can
be useful for handling specific errors in your application. Here's an example:
class MyCustomError(Exception):

pass

def my_function():

# Some condition that warrants raising an error

raise MyCustomError("An error occurred in my_function")

try:

my_function()

except MyCustomError as e:

print(f"Custom error caught: {e}")

In this case, we define a custom exception class MyCustomError, and then raise an instance
of it within my_function(). When the exception is raised, it's caught in the except block,
and the error message is printed.

Using raise allows you to control the flow of your program when unexpected situations
occur, providing a way to handle errors gracefully and provide meaningful feedback to
users or developers.

7. Assert
In Python, the assert statement is used as a debugging aid to test a condition. It ensures
that the condition specified is true. If the condition is false, it raises an AssertionError
exception with an optional error message.

The basic syntax of the assert statement is:


assert condition, "Optional error message"
• condition: A boolean expression that you expect to be true. If this condition
evaluates to False, the AssertionError is raised.

• "Optional error message": An optional message that will be displayed alongside


the AssertionError if the condition is false. This helps in identifying what assertion
failed.

Here's an example of how you can use assert:

def divide(x, y):

assert y != 0, "Divisor cannot be zero"

return x / y

result = divide(10, 2) # This will work fine

print(result)

result = divide(10, 0) # This will raise an AssertionError

print(result) # This line won't be executed

In this example, the assert statement checks if the divisor y is not equal to zero. If y is
zero, it raises an AssertionError with the message "Divisor cannot be zero". This helps to
catch potential bugs or unexpected conditions during development and testing.

It's worth noting that assert statements can be disabled globally by running Python with
the -O option, or individually using the -oo option. In optimized mode, assertions are
ignored and not evaluated. Therefore, it's typically used during development and
debugging, rather than in production code.

You might also like