Course Progress50%
🍎 Python Error Handling Topic 50 / 100
⏳ 8 min read

Exception Handling

Things go wrong. Files don’t exist, users type nonsense, networks drop. try and except let your program handle errors gracefully instead of crashing.

"Every program that talks to the real world will eventually encounter something unexpected. Exception handling is what separates code that crashes from code that recovers."

— ShurAI

What is an Exception?

An exception is an error that happens while the program is running. Without handling, it crashes the whole program with a traceback message:

python — unhandled crash
print(10 / 0)
# ZeroDivisionError: division by zero

int("hello")
# ValueError: invalid literal for int() with base 10: 'hello'

my_list = [1, 2, 3]
print(my_list[10])
# IndexError: list index out of range

try / except — The Basic Pattern

Wrap risky code in try. If something goes wrong, Python jumps to except instead of crashing:

python
try:
    result = 10 / 0           # this will fail
except ZeroDivisionError:
    print("Can't divide by zero!")  # runs instead of crashing

print("Program continues...")      # this still runs!
output
Can't divide by zero!
Program continues...
How try/except flows:
try:
Python runs the code inside. If it succeeds → skip except, continue normally.
↓ error occurs
except:
Python jumps here only if an error happened in try. Handle it gracefully.
↓ always continues
rest of code
Program keeps running normally. No crash.

Catching Multiple Exception Types

Use multiple except blocks to handle different errors differently:

python
def safe_divide(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        print("Error: can't divide by zero")
        return None
    except TypeError:
        print("Error: both values must be numbers")
        return None

print(safe_divide(10, 2))      # 5.0
print(safe_divide(10, 0))      # Error: can't divide by zero
print(safe_divide(10, "x"))    # Error: both values must be numbers

Getting the Error Message with as

python
try:
    with open("missing.txt") as f:
        f.read()
except FileNotFoundError as e:
    print(f"Could not open file: {e}")
    # Could not open file: [Errno 2] No such file or directory: 'missing.txt'

else and finally

else runs only when no error occurred. finally runs always — error or not. Perfect for cleanup:

python
def read_file(filename):
    try:
        f = open(filename)
        content = f.read()
    except FileNotFoundError:
        print(f"File not found: {filename}")
        content = None
    else:
        print("File read successfully!")   # only if no error
        f.close()
    finally:
        print("Done attempting to read file.")  # always runs
    return content
try
Code that might fail. Always runs first.
except
Handle the error. Runs only if try failed.
else
Success code. Runs only if try succeeded.
finally
Cleanup. Runs no matter what.

Common Built-in Exceptions

Exception When it happens
ValueErrorRight type, wrong value — int("hello")
TypeErrorWrong type — "hi" + 5
ZeroDivisionErrorDividing by zero — 10 / 0
FileNotFoundErrorOpening a file that doesn’t exist
KeyErrorDict key doesn’t exist — d["missing"]
IndexErrorList index out of range — lst[99]
AttributeErrorObject doesn’t have that attribute or method

Real Example — Safe User Input

python
def get_age():
    """Ask for age until the user enters a valid number."""
    while True:
        try:
            age = int(input("Enter your age: "))
            if age < 0:
                print("Age can't be negative. Try again.")
            else:
                return age
        except ValueError:
            print("That's not a number. Try again.")

age = get_age()
print(f"You are {age} years old.")
session
Enter your age: hello
That's not a number. Try again.
Enter your age: -5
Age can't be negative. Try again.
Enter your age: 22
You are 22 years old.
Don’t catch everything blindly

Avoid except Exception or bare except: unless you really mean it. Catching every possible error hides real bugs. Always be as specific as possible — catch the exact exception type you expect.

"try/except doesn’t hide errors — it handles them. There’s a big difference. The goal is always to recover gracefully and keep the program running."

— ShurAI

🧠 Quiz — Q1

What happens if code inside a try block raises an exception and there is a matching except block?

🧠 Quiz — Q2

When does the else block run in a try/except/else structure?

🧠 Quiz — Q3

What does except ValueError as e: do?

🧠 Quiz — Q4

When does finally run?