Python Exception Handling: Robust Error Handling & Custom Exceptions

No matter how carefully a programmer designs an algorithm, runtime errors happen: a user enters letters instead of a number, a network connection drops, or a requested file does not exist on disk. Unhandled runtime errors crash programs with ugly tracebacks. Exception Handling allows Python programs to catch errors gracefully and recover without crashing.

Python Built-in Standard Exceptions Hierarchy Diagram

Figure 38.1: Python standard exception hierarchy showing BaseException root and catchable Exception subclasses.


1. The Complete Exception Block: try, except, else, finally

def divide_numbers(a, b):
    try:
        # Code that might raise an exception:
        result = a / b
    except ZeroDivisionError as err:
        # Executes ONLY if ZeroDivisionError occurred:
        print(f"Error caught: Cannot divide by zero! ({err})")
        return None
    except TypeError as err:
        # Executes if wrong data type was passed:
        print(f"Error caught: Numbers must be numeric! ({err})")
        return None
    else:
        # Executes ONLY if NO exception was raised:
        print("Division completed smoothly without errors.")
        return result
    finally:
        # ALWAYS executes no matter what:
        print("Cleaning up resources and logging attempt.")

print("Result 1:", divide_numbers(20, 4))
print("---")
print("Result 2:", divide_numbers(20, 0))

2. Creating Custom User-Defined Exceptions

In professional systems, you can create domain-specific exceptions by subclassing the built-in Exception class:

class InsufficientBalanceError(Exception):
    """Raised when an ATM withdrawal exceeds available balance."""
    def __init__(self, balance, amount):
        super().__init__(f"Attempted to withdraw ₹{amount}, but balance is only ₹{balance}!")
        self.balance = balance
        self.amount = amount

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

try:
    withdraw(1000, 2500)
except InsufficientBalanceError as ex:
    print("Transaction Blocked:", ex)

Frequently Asked Questions (FAQ)

Why is bare 'except:' considered bad practice?

A bare except: catches everything, including system interrupts like KeyboardInterrupt (Ctrl + C) and SystemExit. Always catch specific exceptions (e.g. except (ValueError, KeyError):) or catch except Exception:.
Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Stumbleupon Share on Tumblr Share on Reddit Share on Diggit

You may also like this!