Python

Exception Handling in Python

Exception Handling is a mechanism in Python that allows your program to continue running even when unexpected errors occur. Without handling, any runtime error stops the execution and prints a stack trace.

Python uses the following keywords for exception handling:


1. Basic try-except

Use try when a block may cause an error, and except to handle it.

try:
            num = int(input("Enter a number: "))
            print("You entered:", num)
        except ValueError:
            print("Invalid input! Please enter a number.")
        

If the user inputs text like "abc", int("abc") raises ValueError, and the program continues safely.


2. Handling Multiple Exceptions Separately

Each exception type can be handled independently. Useful when different errors require different messages.

try:
            a = int(input("Enter a number: "))
            b = int(input("Enter another number: "))
            result = a / b
        except ValueError:
            print("Invalid input! Please enter integers.")
        except ZeroDivisionError:
            print("Cannot divide by zero!")
        

Best Practice: Always catch specific exceptions, not generic ones.


3. Catching Multiple Exceptions in One Block

try:
            result = int("abc") / 0
        except (ValueError, ZeroDivisionError) as e:
            print("Error occurred:", e)
        

Use this when the handling logic is the same for multiple exception types.


4. Using else Block

The else block runs only when no exception occurs.

try:
            result = 10 / 2
        except ZeroDivisionError:
            print("Division by zero!")
        else:
            print("Division successful, result:", result)
        

Use Case: Code that should run only if no errors happened.


5. Using finally Block

finally always executes, exceptions or not. Useful for cleanup operations (closing files, releasing database connections, etc.).

try:
            file = open("data.txt", "r")
            data = file.read()
        except FileNotFoundError:
            print("File not found!")
        finally:
            print("Closing file if opened...")
            try:
                file.close()
            except NameError:
                pass
        

Key Point: Even if exception occurs or return is executed, finally still runs.


6. Raising Exceptions Manually

Use raise to throw your own exceptions.

def check_age(age):
            if age < 18:
                raise ValueError("Age must be at least 18")
            return True

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

This is useful for validating input or enforcing business rules.


7. Creating Custom Exception Classes

You can create your own exception types by inheriting from Exception.

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

        def sqrt(num):
            if num < 0:
                raise NegativeNumberError("Cannot compute square root of negative number")
            return num ** 0.5

        try:
            print(sqrt(-9))
        except NegativeNumberError as e:
            print("Custom Error:", e)
        

Custom exceptions make error handling more meaningful and readable.


8. Common Built-In Exceptions


9. Execution Flow Diagram


        try:
            # risky code
        except:
            # runs when error occurs
        else:
            # runs ONLY if no exception occurs
        finally:
            # always runs
        

Flowchart:


            +---------+
            |  try    |
            +----+----+
                    |
                    v
        +---------+---------+
        | Exception Occurred? |
        +----+-----------+---+
            |           |
            Yes          No
            |           |
            v           v
        +-----+----+   +--+-----+
        |  except  |   |  else  |
        +-----+----+   +--+-----+
            \           /
                \         /
                \       /
                v     v
                +----+
                |finally|
                +-------+
        

10. Nested try-except Example

try:
            num = int(input("Enter a number: "))
            try:
                print(10 / num)
            except ZeroDivisionError:
                print("Inner: cannot divide by zero!")
        except ValueError:
            print("Outer: invalid number!")
        

11. Exception Chaining (raise from)

Use raise ... from ... to show the original cause of an error.

try:
            value = int("abc")
        except ValueError as e:
            raise TypeError("Invalid type conversion") from e
        

12. Best Practices