Neural Sync Active
Exception Handling
Registry Synced
Exception Handling
976 words
5 min read
Reading compass
Now · 🎯 Learning Objectives
Exception Handling
Why read this? Errors happen. A user enters text where a number is expected. A file doesn't exist. A network connection drops. Without proper handling, any of these errors crashes your program. Exception handling gives you the power to anticipate problems and respond gracefully — showing helpful messages, retrying operations, or safely shutting down.
🎯 Learning Objectives
By the end of this topic, you will be able to:
- Use
try/exceptblocks to catch and handle exceptions - Handle specific exception types (ValueError, FileNotFoundError, etc.)
- Use
elseandfinallyclauses for cleanup - Raise exceptions with
raisefor input validation - Create custom exception classes
📋 Prerequisites
- File Operations — File errors are common exceptions.
- Basic understanding of control flow.
📖 Core Content
27.1 What Problem Do Exceptions Solve?
Intuition: A program without exception handling is like a car with no airbags or seatbelts. Any small bump causes a crash. Exceptions are your safety system — they catch problems before they crash the program and let you respond appropriately.
27.2 Basic try/except
python# runnable try: num = int(input("Enter a number: ")) print(f"100 / {num} = {100 / num}") except ValueError: print("That's not a valid number!") except ZeroDivisionError: print("Can't divide by zero!") print("Program continues safely...")
How it works:
- Python executes the code in the
tryblock. - If no error occurs,
exceptblocks are skipped. - If a
ValueErroroccurs (e.g., user types "abc"), the first matchingexceptruns. - If a
ZeroDivisionErroroccurs, that handler runs. - Any other exception type would crash the program (not caught).
27.3 Catching Multiple Exceptions
python# runnable try: numbers = [1, 2, 3] index = int(input("Index (0-2): ")) print(f"Value: {numbers[index]}") result = 100 / index print(f"100/{index} = {result}") except (ValueError, IndexError, ZeroDivisionError) as e: print(f"Error occurred: {type(e).__name__}: {e}")
27.4 try/except/else/finally
python# runnable def read_file_safe(filename): """Read a file safely with full exception handling.""" try: f = open(filename, "r") content = f.read() except FileNotFoundError: print(f"Error: '{filename}' not found.") return None except PermissionError: print(f"Error: No permission to read '{filename}'.") return None else: # Runs ONLY if no exception occurred print(f"Successfully read {len(content)} characters.") return content finally: # ALWAYS runs — cleanup code print(f"Finished processing '{filename}'.") if 'f' in locals() and not f.closed: f.close() # Test result = read_file_safe("example.txt") print(f"Result: {result}")
27.5 Raising Exceptions
python# runnable def get_positive_int(prompt): """Get a positive integer from user. Raises ValueError if invalid.""" value = int(input(prompt)) if value <= 0: raise ValueError(f"{value} is not positive!") return value try: age = get_positive_int("Enter your age: ") print(f"You are {age} years old.") except ValueError as e: print(f"Invalid input: {e}")
27.6 Custom Exception Classes
python# runnable class InsufficientFundsError(Exception): """Raised when account balance is too low.""" pass class NegativeAmountError(Exception): """Raised when deposit/withdrawal amount is negative.""" pass class BankAccount: def __init__(self, balance=0): self.balance = balance def withdraw(self, amount): if amount < 0: raise NegativeAmountError("Withdrawal amount can't be negative!") if amount > self.balance: raise InsufficientFundsError(f"Need ₹{amount}, have ₹{self.balance}") self.balance -= amount print(f"Withdrew ₹{amount}. Balance: ₹{self.balance}") acc = BankAccount(1000) try: acc.withdraw(1500) except InsufficientFundsError as e: print(f"Transaction failed: {e}") except NegativeAmountError as e: print(f"Invalid amount: {e}")
27.7 Common Exception Types
| Exception | When It Occurs | Example |
|---|---|---|
ValueError | Wrong value for a function | int("abc") |
TypeError | Wrong type for an operation | "5" + 3 |
IndexError | List index out of range | [1,2][5] |
KeyError | Dictionary key not found | {"a":1}["b"] |
FileNotFoundError | File doesn't exist | open("nope.txt") |
ZeroDivisionError | Division by zero | 10 / 0 |
ImportError | Module not found | import nonexistent |
AttributeError | Object has no attribute | "hello".nonexistent() |
⚠️ Common Pitfalls
Pitfall 1: Bare except: Catches Everything
The mistake:
except: without specifying type catches ALL errors, including Ctrl+C (KeyboardInterrupt), making the program unkillable. Fix: Always specify exception type: except ValueError: or at minimum except Exception as e:.Pitfall 2: Swallowing Errors Silently
The mistake:
except: pass — hides all errors, making debugging impossible. Fix: At minimum log the error: except Exception as e: print(f"Error: {e}") or logging.exception("...").Pitfall 3: Not Cleaning Up Resources
The mistake: Opening a file or network connection in
try and an exception occurs before cleanup. Fix: Use with statement (auto-closes) or finally block for guaranteed cleanup.Pitfall 4: Raising Exception Without Message
The mistake:
raise ValueError without explanation. Fix: Always include a descriptive message: raise ValueError("Age must be positive").📝 Practice Questions
Q1: What's the output if user enters "five"?pythontry: x = int(input("Number: ")) print(10 / x) except ValueError: print("Bad number") except ZeroDivisionError: print("Zero division")Answer:Bad number— theValueErrorfromint("five")is caught. Q2: When does the finally block execute?Answer: ALWAYS — whether an exception occurred or not. It's for cleanup code that must run. Q3: What's wrong with except: (bare except)?Answer: It catches ALL exceptions including SystemExit, KeyboardInterrupt, and GeneratorExit. This can make the program impossible to terminate. Always specify the exception type. Q4: Write a function safe_divide(a, b) that handles ZeroDivisionError and TypeError.Answer:pythondef safe_divide(a, b): try: return a / b except ZeroDivisionError: return None except TypeError: return NoneQ5: What does the else clause in a try/except block do?Answer: Theelseblock runs ONLY if thetryblock did NOT raise an exception. It's useful for code that should run only on success. Q6-10: Additional exception handling questions follow the same format.(Following the established pattern with detailed answers.)
🔗 Cross-References
- Next Topic: Modules & Packages
- Previous Topic: Advanced File Operations
- Reference: Python for Everybody, Chapter 3 (Section 3.7 — "Catching exceptions using try and except")
- Video: L82: Exception handling, L66: Introduction to advanced concepts & exception handling Join Discord Previous26. Advanced File OperationsNext28. Modules & Packages