← Python EnglishChapter 09 of 13

Error Handling

## Learning Objectives - Understand Python exceptions - Use try/except/finally - Raise custom exceptions - Handle specific error types ## Exceptions vs Syntax Errors ### Syntax Errors ```python # These are caught before the program runs if True print("Hello") # File "", line 1 # if True # ^ # SyntaxError: invalid syntax ``` ### Exceptions ```python # These occur during runtime print(10 / 0) # Traceback (most recent call last): # File "", line 1, in # ZeroDivisionError: division by zero ``` ## Basic try/except ### Simple Example ```python try: result = 10 / 0 except ZeroDivisionError: result = 0 print(result) # 0 ``` ### Catching Multiple Exceptions ```python try: value = int(input("Enter a number: ")) result = 10 / value except ValueError: print("That's not a valid number!") except ZeroDivisionError: print("Can't divide by zero!") ``` ### Catching All Exceptions ```python try: result = risky_operation() except Exception as e: print(f"Error: {e}") ``` ### Bare except ```python try: result = risky_operation() except: print("Something went wrong") ``` ## The else Clause ```python try: value = int(input("Enter a number: ")) result = 10 / value except ValueError: print("Invalid input") except ZeroDivisionError: print("Can't divide by zero") else: print(f"Result: {result}") # Only if no exception ``` ## The finally Clause ```python try: file = open("file.txt", "r") content = file.read() except FileNotFoundError: print("File not found") finally: print("This always runs") # file.close() # Better to use context manager ``` ## Common Exception Types ### Built-in Exceptions | Exception | When Raised | |-----------|-------------| | ZeroDivisionError | Division by zero | | ValueError | Wrong value for operation | | TypeError | Wrong type for operation | | IndexError | Index out of range | | KeyError | Key not found in dict | | AttributeError | Attribute not found | | FileNotFoundError | File doesn't exist | | ImportError | Module import fails | ### Examples ```python # IndexError numbers = [1, 2, 3] print(numbers[5]) # IndexError: list index out of range # KeyError d = {"a": 1} print(d["b"]) # KeyError: 'b' # TypeError print("hello" + 5) # TypeError: can only concatenate str # ValueError print(int("abc")) # ValueError: invalid literal ``` ## Raising Exceptions ### raise Statement ```python def divide(a, b): if b == 0: raise ValueError("Cannot divide by zero") return a / b try: result = divide(10, 0) except ValueError as e: print(e) # Cannot divide by zero ``` ### Raising with No Argument ```python try: raise ValueError("Custom error") except ValueError: print("Caught it") raise # Re-raise the same exception ``` ## Custom Exceptions ### Defining Exception Classes ```python class ValidationError(Exception): """Raised when validation fails.""" pass class PositiveNumberError(ValidationError): """Raised when number is not positive.""" def __init__(self, value): self.value = value super().__init__(f"Expected positive number, got {value}") # Using custom exceptions def process_number(n): if n < 0: raise PositiveNumberError(n) return n * 2 try: process_number(-5) except PositiveNumberError as e: print(e) # Expected positive number, got -5 ``` ## Exception Hierarchy ```text BaseException ├── SystemExit ├── KeyboardInterrupt └── Exception ├── StopIteration ├── ArithmeticError │ ├── FloatingPointError │ ├── OverflowError │ └── ZeroDivisionError ├── LookupError │ ├── IndexError │ └── KeyError ├── OSError │ ├── FileNotFoundError │ └── PermissionError └── ... ``` ## Catching Exception Hierarchy ```python # Catch all arithmetic errors (includes ZeroDivisionError, OverflowError) try: result = 10 / 0 except ArithmeticError: print("Math error") # This catches ZeroDivisionError too since it's a subclass ``` ## Practical Patterns ### Exception in Functions ```python def safe_divide(a, b): try: return a / b except ZeroDivisionError: return None result = safe_divide(10, 0) if result is None: print("Division failed") ``` ### Retry Pattern ```python import time def retry(func, max_attempts=3, delay=1): for attempt in range(max_attempts): try: return func() except Exception as e: if attempt == max_attempts - 1: raise print(f"Attempt {attempt + 1} failed: {e}") time.sleep(delay) ``` ### With Resources ```python try: with open("file.txt", "r") as file: content = file.read() except FileNotFoundError: content = "" ``` ## Best Practices 1. **Be specific** - Catch specific exceptions, not bare `except:` 2. **Clean up** - Use `finally` or context managers 3. **Reraise** - Let exceptions propagate when appropriate 4. **Don't suppress** - Don't silently catch exceptions without action 5. **Custom exceptions** - Create specific exceptions for your domain ```python # Good try: result = int(user_input) except ValueError: print("Please enter a valid number") # Bad try: result = int(user_input) except: pass ``` ## Summary - Syntax errors: caught before runtime - Exceptions: occur during execution - Use `try/except` to handle exceptions - `except ExceptionType` catches specific exceptions - `except Exception as e` captures the error object - `else` runs if no exception - `finally` always runs - `raise` triggers an exception - Create custom exceptions by extending `Exception` - Use context managers (`with`) for resource cleanup

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →