Command Palette

Search for a command to run...

Exception Handling

Handling errors gracefully with try-except blocks and custom exceptions.

Try-Except Basics

  • Exceptions are errors that occur during program execution.
  • Use try-except to catch and handle errors.
  • Program continues running after handling exception.
  • Prevents crashes from unexpected errors.
# Without exception handling (crashes)
# result = 10 / 0  # ZeroDivisionError

# With exception handling
try:
    result = 10 / 0
except ZeroDivisionError:
    print("Cannot divide by zero!")
    result = None

print("Program continues...")

Multiple Exceptions

  • Catch different exception types separately.
  • More specific exceptions first, general ones last.
  • Use Exception to catch all exceptions.
def divide(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        print("Cannot divide by zero!")
        return None
    except TypeError:
        print("Invalid types for division!")
        return None
    except Exception as e:
        print(f"Unexpected error: {e}")
        return None

print(divide(10, 2))      # 5.0
print(divide(10, 0))      # Cannot divide by zero!
print(divide(10, "2"))    # Invalid types for division!

Else and Finally

  • else: Runs if no exception occurred
  • finally: Always runs, even if exception occurred
  • Use finally for cleanup (closing files, connections)
try:
    file = open("data.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("File not found!")
else:
    print("File read successfully!")
    print(content)
finally:
    print("Cleanup code runs here")
    # file.close()  # Always close file

# Better with 'with' statement
try:
    with open("data.txt", "r") as file:
        content = file.read()
except FileNotFoundError:
    print("File not found!")

Raising Exceptions

  • Use 'raise' to throw exceptions intentionally.
  • Useful for input validation.
  • Can raise built-in or custom exceptions.
def check_age(age):
    if age < 0:
        raise ValueError("Age cannot be negative!")
    if age < 18:
        raise ValueError("Must be 18 or older!")
    return "Access granted"

try:
    result = check_age(15)
    print(result)
except ValueError as e:
    print(f"Error: {e}")

# Re-raising exceptions
try:
    x = int("abc")
except ValueError:
    print("Invalid number!")
    raise  # Re-raise the same exception

Custom Exceptions

  • Create custom exception classes for specific errors.
  • Inherit from Exception or specific exception types.
  • Add custom attributes and methods.
# Define custom exception
class InsufficientFundsError(Exception):
    pass

# Use custom exception
class BankAccount:
    def __init__(self, initial):
        self.balance = initial
    
    def withdraw(self, requested):
        if requested > self.balance:
            raise InsufficientFundsError("Not enough funds!")
        self.balance = self.balance - requested
        return self.balance

# Test it
account = BankAccount(100)
try:
    account.withdraw(150)
except InsufficientFundsError as e:
    print(f"Error: {e}")  # Error: Not enough funds!