CBSE Class 12 CS (083) - Exception Handling

Exception Handling

Exceptions are runtime errors that disrupt the normal flow of program execution. Python provides a robust exception handling mechanism using try, except, else, finally, and raise statements. This chapter covers all aspects of exception handling as per the CBSE Class 12 Computer Science syllabus.

1. Introduction to Exceptions

An exception is an unexpected event that occurs during program execution. It disrupts the normal flow of the program's instructions.

Common scenarios causing exceptions:

  • Dividing a number by zero.
  • Accessing an index outside list bounds.
  • Opening a file that does not exist.
  • Converting an invalid string to an integer.
  • Importing a module that does not exist.

Exception vs Error: An error indicates a serious problem that should not be caught (syntax errors), while an exception can be caught and handled.

2. Common Built-in Exceptions

ExceptionCauseExample
ZeroDivisionErrorDivision or modulo by zero10 / 0
ValueErrorInvalid value for a functionint("abc")
TypeErrorInvalid operation between types"2" + 3
IndexErrorList index out of rangelst[10]
KeyErrorDictionary key not foundd["xyz"]
FileNotFoundErrorFile does not existopen("nofile.txt")
ImportErrorModule import failsimport nonexistent
AttributeErrorAttribute or method not found"abc".nonexistent()
StopIterationIterator has no more itemsnext(empty_iter)

3. The try-except Block

The try block contains code that may raise an exception. The except block handles the exception if it occurs.

try:
num = int(input("Enter a number: "))
result = 10 / num
print("Result:", result)
except ZeroDivisionError:
print("Cannot divide by zero.")
except ValueError:
print("Invalid input. Please enter a valid number.")

Syntax:

try:
# Code that may raise exception
except ExceptionType:
# Handle the exception

4. Handling Multiple Exceptions

Multiple exceptions can be handled in two ways:

Multiple except blocks:

try:
x = int(input("Enter first number: "))
y = int(input("Enter second number: "))
print(x / y)
except ZeroDivisionError:
print("Division by zero not allowed.")
except ValueError:
print("Invalid input. Enter numeric values.")

Single except with tuple:

try:
x = int(input("Enter a number: "))
result = 100 / x
print(result)
except (ZeroDivisionError, ValueError) as e:
print("Error occurred:", e)

5. The else Clause

The else block executes only when no exception occurs in the try block.

try:
num = int(input("Enter a number: "))
result = 100 / num
except ZeroDivisionError:
print("Cannot divide by zero.")
except ValueError:
print("Invalid input.")
else:
print("Division successful. Result:", result)

6. The finally Clause

The finally block always executes regardless of whether an exception occurs or not. It is commonly used for cleanup operations like closing files or releasing resources.

try:
f = open("data.txt", "r")
content = f.read()
except FileNotFoundError:
print("File not found.")
finally:
f.close()
print("File closed.")

7. Raising Exceptions with raise

The raise statement is used to explicitly raise an exception. It can be used both inside and outside try blocks.

def check_age(age):
if age < 0:
raise ValueError("Age cannot be negative.")
elif age > 150:
raise ValueError("Age seems unrealistic.")
else:
print("Valid age:", age)

try:
check_age(-5)
except ValueError as e:
print("Error:", e)

Re-raising an exception:

try:
x = int("abc")
except ValueError:
print("Invalid input caught.")
raise # Re-raise the same exception

8. The assert Statement

The assert statement is used for debugging. It raises an AssertionError if a condition is False.

def divide(a, b):
assert b != 0, "Denominator cannot be zero"
return a / b

print(divide(10, 2)) # Output: 5.0
print(divide(10, 0)) # Raises AssertionError

Assertions can be disabled with the -O (optimize) flag when running Python.

9. Creating Custom Exceptions

You can create custom exceptions by defining a new class that inherits from the built-in Exception class.

class NegativeNumberError(Exception):
"""Raised when a negative number is provided."""
pass

class InsufficientFundsError(Exception):
def __init__(self, balance, amount):
super().__init__(f"Insufficient funds. Balance: {balance}, Required: {amount}")
self.balance = balance
self.amount = amount

def withdraw(balance, amount):
if amount > balance:
raise InsufficientFundsError(balance, amount)
return balance - amount

10. Getting Exception Information

Use the as keyword to capture exception details.

try:
x = 10 / 0
except ZeroDivisionError as e:
print("Exception type:", type(e).__name__)
print("Exception args:", e.args)
print("Exception message:", str(e))

The sys.exc_info() function provides detailed exception information including traceback.

11. Nested try-except Blocks

try:
try:
num = int(input("Enter number: "))
result = 10 / num
print("Result:", result)
except ZeroDivisionError:
print("Inner: Division by zero.")
except ValueError:
print("Outer: Invalid input.")

If the inner block does not handle an exception, it propagates to the outer block.

12. Best Practices

  • Catch specific exceptions instead of using a bare except:.
  • Use finally for cleanup operations (closing files, releasing resources).
  • Avoid catching exceptions and then silently ignoring them.
  • Use else block for code that should run only when no exception occurs.
  • Raise meaningful exceptions with descriptive messages.
  • Do not use exceptions for normal control flow.
  • Log exception details for debugging purposes.
  • Keep try blocks small and focused.

13. Revision Questions and Answers

Very Short Answer Questions

1. What is an exception?
An exception is an unexpected event that occurs during program execution and disrupts normal flow.

2. Which keywords are used for exception handling in Python?
try, except, else, finally, and raise.

3. What is the purpose of the finally block?
The finally block always executes, regardless of whether an exception occurred or not, and is used for cleanup operations.

4. Which statement is used to manually raise an exception?
The raise statement.

5. What does the else block do in a try-except statement?
The else block executes only when no exception occurs in the try block.

Short Answer Questions

1. Differentiate between except and finally.
The except block executes only when a specific exception occurs in the try block. The finally block always executes regardless of whether an exception occurred, and is primarily used for cleanup tasks like closing files or releasing resources.

2. How can you handle multiple exceptions in a single try block?
Multiple exceptions can be handled using multiple except blocks (one for each exception type) or a single except block with a tuple of exception types: except (ValueError, TypeError) as e:.

Long Answer Questions

1. Write a program that handles division by zero, invalid input, and includes else and finally blocks.

try:
numerator = float(input("Enter numerator: "))
denominator = float(input("Enter denominator: "))
result = numerator / denominator
except ZeroDivisionError:
print("Error: Cannot divide by zero.")
except ValueError:
print("Error: Please enter numeric values only.")
else:
print(f"Result: {result:.2f}")
finally:
print("Execution completed.")

2. Explain the difference between syntax errors and exceptions with examples.
Syntax errors occur when Python cannot parse the code due to incorrect grammar, such as missing a colon. They prevent the program from running. Exceptions occur during execution of syntactically correct code, such as dividing by zero. Syntax errors must be fixed before running; exceptions can be caught and handled using try-except blocks.