Python Exception Handling

Exception handling is an essential part of writing robust Python programs. It allows your program to respond to runtime errors, ensuring that the program doesn't crash unexpectedly.


Python Errors and Exceptions

  • Errors: An error occurs in Python when something goes wrong during program execution. Errors can be of two types:

    • Syntax Error: An error that occurs when the Python code does not follow the correct syntax. This prevents the code from being parsed and executed.
    • Runtime Error: These errors occur during program execution, such as trying to divide by zero or accessing an invalid index in a list.
  • Exceptions: An exception is a special kind of runtime error that can be caught and handled using Python's exception handling mechanisms (try, except, finally).


Introduction to Exceptions

An exception is an event that disrupts the normal flow of a program's execution. When an error occurs, Python raises an exception that can be handled by the programmer to manage the situation.


Basic Syntax of Exception Handling

Python provides the try, except, else, and finally blocks to handle exceptions.

  • try Block: Code that might raise an exception is placed inside the try block.
  • except Block: If an exception is raised in the try block, the code in the except block is executed.
  • else Block: If no exception is raised, the code in the else block is executed.
  • finally Block: This block always runs, regardless of whether an exception is raised or not. It is usually used for cleanup actions.

Basic Syntax:

try:
    # Code that might raise an exception
except SomeException:
    # Code that runs if an exception occurs
else:
    # Code that runs if no exception occurs
finally:
    # Code that always runs, regardless of exceptions

Example: Basic Exception Handling

Example:

try:
    x = 10 / 0  # Division by zero error
except ZeroDivisionError:
    print("You cannot divide by zero!")
else:
    print("Division was successful.")
finally:
    print("This will always execute.")

Output:

You cannot divide by zero!
This will always execute.

Handling Multiple Exceptions

You can handle multiple exceptions by using multiple except blocks or a single except block with multiple exception types.

  • Handling Multiple Exceptions:
try:
    x = int(input("Enter a number: "))
    result = 10 / x
except ValueError:
    print("Invalid input! Please enter an integer.")
except ZeroDivisionError:
    print("Cannot divide by zero!")
else:
    print(f"The result is {result}")
finally:
    print("Execution complete.")

Catching All Exceptions

Sometimes, you may want to catch all exceptions without specifying each one. You can use a generic except block.

Example:

try:
    # Some code that might raise any exception
    x = int("hello")
except Exception as e:
    print(f"An error occurred: {e}")
finally:
    print("Execution complete.")

Output:

An error occurred: invalid literal for int() with base 10: 'hello'
Execution complete.

Custom Exception Handling

You can define custom exceptions by creating a new class that inherits from Python's built-in Exception class.

  • Creating a Custom Exception:
class CustomError(Exception):
    pass

try:
    raise CustomError("This is a custom error")
except CustomError as ce:
    print(f"Caught an error: {ce}")

Output:

Caught an error: This is a custom error

Using raise to Trigger Exceptions

The raise statement is used to trigger exceptions manually. You can raise built-in exceptions or custom exceptions.

Example:

def check_age(age):
    if age < 18:
        raise ValueError("Age must be 18 or older")
    else:
        print("Age is valid")

try:
    check_age(16)
except ValueError as e:
    print(e)

Output:

Age must be 18 or older

Best Practices for Exception Handling

  1. Catch specific exceptions: Always catch specific exceptions rather than a generic Exception to avoid masking other errors.
  2. Avoid using empty except blocks: Empty blocks can hide bugs, so ensure you handle exceptions properly.
  3. Log exceptions: Instead of printing exceptions, log them for debugging purposes, especially in production code.
  4. Use finally for cleanup: Use the finally block for operations like closing files or database connections, which should happen regardless of success or failure.
Task

Practice: Exception Handling in Python

Objective: Strengthen your exception handling skills by addressing various common scenarios.

  1. Basic Exception Handling:

    • Write a program that prompts the user to enter two numbers. Then, divide the first number by the second. Ensure the program handles the following exceptions:
      • ZeroDivisionError: When dividing by zero.
      • ValueError: When the user enters non-numeric values.
    try:
        num1 = float(input("Enter the first number: "))
        num2 = float(input("Enter the second number: "))
        result = num1 / num2
    except ZeroDivisionError:
        print("Error: Cannot divide by zero.")
    except ValueError:
        print("Error: Please enter valid numbers.")
    else:
        print(f"The result is: {result}")
    
  2. Handling Multiple Exceptions:

    • Write a program that prompts the user for a number. If the input is not a valid number, raise a ValueError. If the number is less than 10, raise a custom exception ValueTooSmallError.
    class ValueTooSmallError(Exception):
        pass
    
    try:
        num = float(input("Enter a number: "))
        if num < 10:
            raise ValueTooSmallError("The number is too small.")
    except ValueError:
        print("Error: Invalid input. Please enter a valid number.")
    except ValueTooSmallError as e:
        print(f"Error: {e}")
    
  3. Custom Exceptions:

    • Define a custom exception NegativeValueError that is raised when the user inputs a negative number. Handle this exception appropriately.
    class NegativeValueError(Exception):
        def __init__(self, message="Negative value not allowed"):
            self.message = message
            super().__init__(self.message)
    
    try:
        value = float(input("Enter a positive number: "))
        if value < 0:
            raise NegativeValueError()
    except NegativeValueError as e:
        print(f"Error: {e}")
    
  4. Using the finally Block:

    • Write a program that opens a file to read its contents. Ensure the file is closed after reading, even if an exception occurs while accessing the file.
    try:
        file = open("sample.txt", "r")
        contents = file.read()
        print(contents)
    except FileNotFoundError:
        print("Error: The file was not found.")
    finally:
        if 'file' in locals():
            file.close()
            print("File has been closed.")
    

Copyright © 2025 Devship. All rights reserved.

Made by imParth