try:
    num1 = float(input("Enter first number: "))
    num2 = float(input("Enter second number: "))
    result = num1 / num2
    print(f"Result: {result}")
except ValueError:
    print("Please enter valid numbers!")
except ZeroDivisionError:
    print("Cannot divide by zero!")Exception Handling
Understanding Exceptions
By now, you will almost certainly have encountered exceptions - error messages that appear when Python doesn’t like what you’ve asked it to do. For example:
Attempting to access the 5th element (index 4, remember we start counting from 0!) of a list with only 3 elements raises an IndexError.
Another common example:
Notice these have different error types: IndexError and TypeError. Python has many different exception types to describe different problems.
The Try-Except Construct
If errors are simply coding mistakes, it’s useful to have the program terminate immediately so we can fix them. However, in real code, problems may arise for reasons beyond the programmer’s control - perhaps the user provided incorrect input. We can catch and handle exceptions gracefully using try...except...:
try:
    [code that may fail]
except:
    [code to handle the error]When Python encounters a try...except... block: 1. It attempts to execute the code in the try block 2. If successful, the except block is never executed 3. If an error occurs, Python immediately jumps to the except block 4. After handling the error, execution continues after the try...except...
Example:
The EAFP Model
This error handling approach is called EAFP: “Easier to Ask Forgiveness than Permission”. Rather than verifying everything is correct before an operation (which can be tedious and inefficient), we assume everything will work and deal with any problems that arise.
Catching Specific Exceptions
A bare except: catches all errors, which can hide bugs. Consider this code with a typo:
This will always say “not a valid number” even when the real problem is the undefined variable z. This is a NameError, not the ValueError we intended to catch.
Better approach: Specify the exception type:
Now our typo would be immediately obvious, but valid user input errors are handled gracefully.
Multiple Exception Handlers
You can catch multiple exception types:
# Catch multiple types in one block
try:
    [code]
except (ValueError, TypeError):
    [code]Or handle different exceptions differently:
try:
    [code]
except ValueError:
    [handle ValueError]
except TypeError:
    [handle TypeError]
except:
    [handle any other exception]Exceptions for Control Flow
Exception handling can be a central part of code design. Here’s an example using exceptions to control loop termination:
This works, but a regular for loop would be cleaner:
It’s tempting to use try...except... everywhere to suppress error messages. This usually makes bugs harder to find. Only use exception handling for: - Predictable error cases (like user input) - Production code that must be robust - Situations where the error is expected and meaningful
Accessing Error Information
Sometimes you need details about the error that occurred:
try:
    [code]
except <ErrorType> as <variable>:
    [code using variable]Example:
The Finally Block
Sometimes you want code to execute regardless of whether an error occurred. Use finally:
try:
    [code]
finally:
    [always executed]The finally block executes: - After successful completion of try, OR - Before an error is propagated
Common uses for finally: - Close files - Save state - Clean up temporary resources - Log progress
Raising Exceptions
You can raise your own exceptions using raise:
raise <ErrorType>
raise <ErrorType>(<message>)Example:
Practical Example: Robust Data Loading
Here’s how exceptions enable clean control flow for robust data loading:
Common Exception Types
Here are some common exceptions you’ll encounter:
- ValueError- Invalid value (e.g.,- int("hello"))
- TypeError- Wrong type (e.g.,- 1 + "hello")
- IndexError- Index out of range
- KeyError- Dictionary key doesn’t exist
- FileNotFoundError- File doesn’t exist
- ZeroDivisionError- Division by zero
- NameError- Variable doesn’t exist
- AttributeError- Object doesn’t have that attribute
Summary
Key concepts from this section:
- Use try...except...to handle errors gracefully
- Catch specific exception types, not all exceptions
- Access error details with except ErrorType as variable:
- Use finallyfor cleanup code
- Raise exceptions with raise ErrorType(message)
- Follow EAFP: Easier to Ask Forgiveness than Permission
Exception handling makes code robust and user-friendly, but don’t overuse it - let genuine bugs show themselves!
