Courses/Python/Exception Handling

    Lesson 10 • Intermediate

    Exception Handling in Python

    Learn to detect, catch, and manage errors gracefully so your programs never crash unexpectedly.

    What You'll Learn in This Lesson

    • What exceptions are and why programs crash without handling
    • How to use try / except to catch errors gracefully
    • How to catch specific exception types (ValueError, KeyError, etc.)
    • How to capture the error message with as e
    • The else and finally blocks and when to use them
    • How to raise your own exceptions with raise

    What Are Exceptions?

    When something goes wrong in your Python code — like dividing by zero or opening a missing file — Python raises an exception. Without handling, your program crashes.

    See an Exception

    Run this to see what an unhandled exception looks like

    Try it Yourself »
    Python
    # This code will crash without exception handling
    result = 10 / 0  # ZeroDivisionError!
    print("This line never runs")

    Why Handle Exceptions?

    Without Exception HandlingWith Exception Handling
    Program crashes completelyProgram continues running
    Confusing error messagesUser-friendly messages
    Data might be lostData is saved safely
    Resources left openResources cleaned up properly

    The try-except Block

    Wrap risky code in a try block. If an error occurs, the except block handles it.

    SyntaxWhat It Does
    try:Code that might fail goes here
    except:Runs if an error occurs in try

    Basic Try-Except

    Catch any error

    Try it Yourself »
    Python
    try:
        result = 10 / 0
        print("Result:", result)
    except:
        print("Oops! Something went wrong.")
    
    print("Program continues running!")

    Catching Specific Exceptions

    Always catch specific exception types. This is the professional way.

    Catch Specific Exception

    Catch only ValueError

    Try it Yourself »
    Python
    # Catching a specific exception type
    try:
        number = int("hello")  # Can't convert "hello" to a number
    except ValueError:
        print("That's not a valid number!")
    
    # This only catches ValueError, not other errors

    Common Exception Types

    Here are the exceptions you'll encounter most often:

    ExceptionWhen It HappensExample
    ValueErrorWrong value typeint("abc")
    TypeErrorWrong operation for type"5" + 3
    ZeroDivisionErrorDividing by zero10 / 0
    IndexErrorInvalid list indexmy_list[100]
    KeyErrorMissing dictionary keymy_dict["name"]
    FileNotFoundErrorFile doesn't existopen("missing.txt")
    NameErrorVariable not definedprint(xyz)

    Different Exception Types

    See IndexError and KeyError

    Try it Yourself »
    Python
    # Try different exceptions
    my_list = [1, 2, 3]
    
    try:
        print(my_list[10])  # IndexError
    except IndexError:
        print("Index out of range!")
    
    # Try this with a dictionary
    my_dict = {"name": "Alice"}
    try:
        print(my_dict["age"])  # KeyError
    except KeyError:
        print("Key not found!")

    Catching Multiple Exceptions

    You can handle different exceptions differently:

    Multiple Except Blocks

    Handle different errors differently

    Try it Yourself »
    Python
    user_input = "abc"  # Try changing to "0" or "5"
    
    try:
        number = int(user_input)
        result = 100 / number
        print("Result:", result)
    except ValueError:
        print("Please enter a valid number!")
    except ZeroDivisionError:
        print("Cannot divide by zero!")
    
    print("Program continues...")

    Or handle them together if the response is the same:

    Group Exceptions

    Handle multiple types the same way

    Try it Yourself »
    Python
    try:
        risky = 10 / int("zero")
    except (ValueError, ZeroDivisionError):
        print("Invalid input - please try again!")

    Getting the Error Message

    Use as to capture the error details:

    Capture Error Message

    Get details about what went wrong

    Try it Yourself »
    Python
    try:
        result = 10 / 0
    except ZeroDivisionError as e:
        print(f"Error occurred: {e}")
        # e contains the error message
    
    # This is helpful for logging and debugging

    The else Block

    The else block runs only if NO exception occurred:

    BlockWhen It Runs
    try:Always tries to run
    except:Only if error in try
    else:Only if NO error in try

    The else Block

    Code that runs on success

    Try it Yourself »
    Python
    number = "5"  # Try changing to "abc"
    
    try:
        result = int(number)
    except ValueError:
        print("Invalid number!")
    else:
        print(f"Success! You entered: {result}")
        print(f"Doubled: {result * 2}")

    The finally Block

    The finally block always runs, whether there was an error or not. Perfect for cleanup.

    The finally Block

    Code that always runs

    Try it Yourself »
    Python
    print("Starting operation...")
    
    try:
        result = 10 / 2  # Try changing to 10 / 0
        print(f"Result: {result}")
    except ZeroDivisionError:
        print("Cannot divide by zero!")
    finally:
        print("Cleanup complete!")  # Always runs
    
    print("Done!")

    The Complete Structure

    All four blocks together:

    try:
        # Risky code here
    except SomeError:
        # Handle the error
    else:
        # Runs if no error
    finally:
        # Always runs (cleanup)

    Complete Try Structure

    try-except-else-finally

    Try it Yourself »
    Python
    filename = "data.txt"
    
    try:
        # Simulate file operation
        print(f"Trying to open {filename}...")
        # file = open(filename)  # Would cause FileNotFoundError
        data = "Sample data"  # Simulated success
    except FileNotFoundError:
        print("File not found!")
        data = None
    else:
        print("File read successfully!")
        print(f"Data: {data}")
    finally:
        print("Operation complete - resources cleaned up.")

    Raising Exceptions

    Use raise to trigger an exception yourself. This is useful for validating data.

    Raise Your Own Exceptions

    Trigger errors for invalid data

    Try it Yourself »
    Python
    def set_age(age):
        if age < 0:
            raise ValueError("Age cannot be negative!")
        if age > 150:
            raise ValueError("Age seems unrealistic!")
        return age
    
    # Test it
    try:
        my_age = set_age(-5)  # Try 25 or 200
    except ValueError as e:
        print(f"Error: {e}")

    Common Mistakes to Avoid

    MistakeProblemFix
    except:Catches everything, hides bugsexcept ValueError:
    Large try blockHard to know what failedPut only risky code in try
    Empty except blockError is silently ignoredAt least log the error
    Catching too highexcept Exception catches allBe specific about types
    Not cleaning upFiles/connections left openUse finally or with

    Good vs Bad Exception Handling

    See why specific exceptions are better

    Try it Yourself »
    Python
    # BAD - Catches everything, hides bugs
    try:
        result = 10 / my_variable  # NameError hidden!
    except:
        print("Something went wrong")
    
    # GOOD - Specific exceptions
    try:
        result = 10 / 0
    except ZeroDivisionError:
        print("Cannot divide by zero")
    # NameError will still crash (and we'll notice the bug!)

    Practical Example: Safe Number Input

    A function that safely gets a number from user input:

    Safe Number Input

    Handle invalid user input gracefully

    Try it Yourself »
    Python
    def get_number(prompt, default=0):
        """Safely get a number, return default if invalid."""
        user_input = input(prompt)  # In practice, this would be real input
        try:
            return float(user_input)
        except ValueError:
            print(f"Invalid input, using default: {default}")
            return default
    
    # Simulate with different inputs
    test_inputs = ["42", "3.14", "hello", ""]
    
    for test in test_inputs:
        print(f"Input: '{test}'")
        try:
            result = float(test) if test else 0
        
    ...

    Practical Example: Calculator

    A safe calculator that handles errors:

    Safe Calculator

    Calculator with full error handling

    Try it Yourself »
    Python
    def safe_calculate(a, b, operation):
        """Perform calculation with error handling."""
        try:
            if operation == "+":
                return a + b
            elif operation == "-":
                return a - b
            elif operation == "*":
                return a * b
            elif operation == "/":
                return a / b
            else:
                raise ValueError(f"Unknown operation: {operation}")
        except ZeroDivisionError:
            return "Error: Cannot divide by zero"
        except TypeError:
         
    ...

    Practical Example: Data Processor

    Process a list of data, handling errors without stopping:

    Robust Data Processing

    Skip bad data, keep processing

    Try it Yourself »
    Python
    def process_data(data_list):
        """Process each item, skip invalid ones."""
        results = []
        errors = []
        
        for i, item in enumerate(data_list):
            try:
                # Try to convert to number and double it
                result = float(item) * 2
                results.append(result)
            except (ValueError, TypeError) as e:
                errors.append(f"Item {i}: {item} - {e}")
        
        return results, errors
    
    # Test with mixed data
    data = ["10", "5.5", "hello", "20", None, "15"]
    resu
    ...

    Summary: Quick Reference

    KeywordPurposeExample
    try:Code that might failtry: x = 1/0
    except Type:Handle specific errorexcept ValueError:
    except Type as e:Capture error messageexcept ValueError as e:
    else:Runs if no errorelse: print("OK")
    finally:Always runs (cleanup)finally: file.close()
    raiseTrigger an exceptionraise ValueError("!")

    Key Takeaways:

    • • Always catch specific exception types
    • • Use finally for cleanup that must always happen
    • • Use else for code that should only run on success
    • Raise exceptions early when you detect invalid data
    • • Never use bare except: in production code

    What's Next?

    You now know how to protect your programs from crashing and handle errors gracefully. Exception handling is essential for building reliable, professional Python applications.

    Next up: Lesson 11 – Modules and Packages — Learn how to organize your code into reusable modules and use Python's powerful standard library.

    🎉

    Lesson 10 done — your programs are now crash-proof!

    try/except, else, finally, raise — you know the full exception handling toolkit. This is what separates fragile scripts from professional, production-ready code.

    🚀 Up next: Modules & Packages — discover Python's vast library ecosystem and learn to organise your own code into reusable files.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service