Python Series track

Week 05 · Intermediate Track

Week 5 — Exception Handling

Write robust programs by handling errors gracefully. Learn the full try/except/else/finally pattern, re-raise exceptions, and define custom exception classes.

Intermediate Track2 min readFree lesson

Level: Intermediate | Prerequisite: Week 4

Learning Goals

  • Know each section of try/except/else/finally
  • Distinguish types of exceptions and handle them
  • Create user-defined exceptions
  • Intentionally raise exceptions (raise)

1. What is an Exception

An error that occurs during execution. If not handled, the program terminates.

print(10 / 0)         # ZeroDivisionError
print(int("abc"))     # ValueError
print([1,2][5])       # IndexError

2. try / except

try:
    n = int(input("Number:"))
    print(10 / n)
except ValueError:
    print("Not a number")
except ZeroDivisionError:
    print("Cannot divide by 0")
except Exception as e:
    print(f"Other error: {e}")

3. else / finally

  • else: Executes when try finishes without exceptions
  • finally: Always executes regardless of exceptions (cleanup tasks)
try:
    f = open("data.txt")
except FileNotFoundError:
    print("No file")
else:
    print(f.read())
    f.close()
finally:
    print("Cleanup complete")

4. raise

Intentionally raise an exception.

def withdraw(balance, amount):
    if amount > balance:
        raise ValueError("Insufficient balance")
    return balance - amount

5. User-Defined Exceptions

Inherit from Exception.

class InsufficientFundsError(Exception):
    pass

def transfer(account, amount):
    if account.balance < amount:
        raise InsufficientFundsError(f"Balance {account.balance} < Request {amount}")

6. Exception Chaining

Raise a new exception while wrapping an existing one.

try:
    int("abc")
except ValueError as e:
    raise RuntimeError("Input processing failed") from e

Key Examples (examples/)

File Content
01_try_except.py Basic try/except
02_else_finally.py else, finally
03_raise.py raise and validation
04_custom.py User-defined exception

⚠️ Common Mistakes

  1. Too broad except
    try:
        ...
    except:           #All exceptions (including KeyboardInterrupt) — dangerous
        pass
    

→ Specify the narrowest possible exception class.

  1. except ... as e: pass — Hides errors. At least log them.

  2. return in finally — Can override return values of try.

  3. Order of except — Narrow exceptions (FileNotFoundError) first, broader ones (OSError) later.

❓ FAQ

Q1. Should try be wrapped around every function? A. No. Only in places where recovery is possible. Usually user input, file I/O, network calls.

Q2. What is the difference between Exception and BaseException? A. BaseException is the top-level. KeyboardInterrupt and SystemExit are also included. Generally, only up to Exception is caught.

Q3. Exception vs return value (None / -1)? A. Exceptions clearly indicate "not normal flow." For normal situations like "not found" in searches, None is recommended.

📝 Exercises (exercises/)

  • exercise1.md — safe integer input (read_int)
  • exercise2.md — user-defined exception (InvalidScoreError)
  • exercise3.md — file read exception handling

Next Week

Week 6. File Input/Output

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

examples/01_try_except.pyPython
try:
    n = int(input("Number:"))
    print(f"10 / {n} = {10 / n}")
except ValueError:
    print("Not a number")
except ZeroDivisionError:
    print("Cannot divide by 0")
except Exception as e:
    print(f"Other error: {type(e).__name__}: {e}")
examples/02_else_finally.pyPython
import os

#Temporary file
TMP = "tmp_demo.txt"
with open(TMP, "w") as f:
    f.write("hello
Hello")

try:
    f = open(TMP, encoding="utf-8")
except FileNotFoundError:
    print("No file")
else:
    print("Content:", f.read())
    f.close()
finally:
    print("Organizing")
    os.remove(TMP)
examples/03_raise.pyPython
def withdraw(balance, amount):
    if amount < 0:
        raise ValueError("The amount must be positive")
    if amount > balance:
        raise ValueError(f"Insufficient balance: {balance} < {amount}")
    return balance - amount

print(withdraw(1000, 300))

try:
    withdraw(1000, -10)
except ValueError as e:
    print("Failure:", e)

try:
    withdraw(1000, 5000)
except ValueError as e:
    print("Failure:", e)
examples/04_custom.pyPython
class InsufficientFundsError(Exception):
    """Occurs when there is insufficient balance"""

class Account:
    def __init__(self, owner, balance):
        self.owner = owner
        self.balance = balance

    def withdraw(self, amount):
        if amount > self.balance:
            raise InsufficientFundsError(
                f"{self.owner}: Balance {self.balance} < Request {amount}"
            )
        self.balance -= amount

a = Account("Hong Gil-dong", 1000)
a.withdraw(300)
print(a.balance)

try:
    a.withdraw(5000)
except InsufficientFundsError as e:
    print("Custom exception:", e)

Assignment

Goal

Write the function read_int(prompt) that asks again if input is incorrect.

Requirements

  • Repeat until only integers are received
  • Friendly message when input is incorrect

Example of use

n = read_int("Please enter your age:")
#User enters "abc" → "Please enter numbers only" → Prompt again

Assignment 2. User-Defined Exception InvalidScoreError

Goal

Create an exception that occurs when the score is not in the range 0~100.

Requirements

  • class InvalidScoreError(Exception): ...
  • validate_score(s) function: if outside 0~100, raise InvalidScoreError
  • main: input score → verify → print grade if normal

Assignment 3. File Reading Exception Handling

Goal

Receive the file path and print its contents. Handle various exceptions.

Exceptions to handle

  • FileNotFoundError — "File not found: ..."
  • PermissionError — "Permission denied: ..."
  • UnicodeDecodeError — "Encoding error: ..."

Example of use

Path: data.txt
File not found: data.txt

Path: /etc/shadow
Permission denied: /etc/shadow
Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

solution1.pyPython
def read_int(prompt):
    while True:
        try:
            return int(input(prompt))
        except ValueError:
            print("Please enter only integers")

n = read_int("Please enter your age:")
print(f"Age: {n}")
solution2.pyPython
class InvalidScoreError(Exception):
    pass

def validate_score(s):
    if not (0 <= s <= 100):
        raise InvalidScoreError(f"It must be in the range 0~100: {s}")

def grade(s):
    validate_score(s)
    if s >= 90: return "A"
    if s >= 80: return "B"
    if s >= 70: return "C"
    if s >= 60: return "D"
    return "F"

while True:
    try:
        score = int(input("Score:"))
        print(f"Grade: {grade(score)}")
        break
    except (ValueError, InvalidScoreError) as e:
        print("Failure:", e)
solution3.pyPython
path = input("Path:").strip()

try:
    with open(path, encoding="utf-8") as f:
        print(f.read())
except FileNotFoundError:
    print(f"File not found: {path}")
except PermissionError:
    print(f"Permission denied: {path}")
except UnicodeDecodeError:
    print(f"Encoding error: {path}")
except OSError as e:
    print(f"Other OS error: {e}")

Learn this lesson with a mentor

Work through the Python Series track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now