Module: Computer Programming for Engineers - Exceptions and Error Handling
Error Handling and Debugging Resources
- When an error occurs during programming, it is recommended to search for the error message online (e.g., Google) to find notes and solutions from other programmers.
- Useful developer websites for troubleshooting include:
- Stack Overflow
- ChatGPT
- Practical debugging techniques:
- Use the
print() function to check the current values of variables at different stages of the program.
- Use pythontutor.com to check the program's execution step by step with visual representations.
- Use Exceptions to prevent the program from crashing when errors occur.
Introduction to Exceptions
- Definition: Exceptions are errors that occur due to circumstances often beyond the programmer's direct control.
- Common Causes:
- Invalid data is input by the user (e.g., entering text when a number is expected).
- A file cannot be accessed (e.g., file not found or permission denied).
- Errors resulting specifically from the user’s fault.
- Programmer's Responsibility:
- A programmer must anticipate potential exceptions.
- Code must be included to work around the occurrence of these exceptions to ensure program stability.
- Example of an Unhandled Exception:
- Code:
num = int(input('Enter a number: '))
- Input: abc
- Result: ValueError: invalid literal for int() with base 10: 'abc'
The try ~ except Statement
- The
try ~ except statement is used to handle errors so that the program continues to run even when an error occurs. - Basic Syntax Structure:
-
try:: Contains the code block that can potentially generate errors.
- except:: Contains the code block that handles the error if one occurs in the try block. - Example Implementation:
- Code:
python
try:
num = int(input('Enter a number: '))
except:
print('Your input is not a number')
- Execution: If the user enters abc, the program outputs Your input is not a number instead of crashing.
Types and Hierarchy of Exceptions
- Common Exception Types:
-
FileNotFoundError: Raised when a file or directory is requested but doesn't exist.
- IndexError: Raised when a sequence subscript is out of range.
- ZeroDivisionError: Raised when the second argument of a division or modulo operation is zero.
- NameError: Raised when a local or global name is not found.
- ValueError: Raised when a function receives an argument of the correct type but an inappropriate value.
- AttributeError: Raised when an attribute reference or assignment fails.
- ImportError: Raised when the import statement has troubles trying to load a module. - Exception Hierarchy:
-
BaseException (The root of the exception hierarchy)
- SystemExit
- KeyboardInterrupt
- GeneralExit
- Exception (Common base class for non-exit exceptions)
- StopIteration
- ArithmeticError
- ZeroDivisionError
- LookupError
- IndexError
- SyntaxError
Catching Specific Errors
- Programs can be designed to respond differently based on the specific type of error encountered.
- Example with Multiple Except Blocks:
- Code:
python
try:
number = int(input("Enter a number: "))
result = 10 / number
print("Result:", result)
except ValueError:
print("That's not a number!")
except ZeroDivisionError:
print("Can't divide by zero!")
- Scenario 1: Input is abc. The except ValueError block catches it and prints That's not a number!.
- Scenario 2: Input is 0. The except ZeroDivisionError block catches it and prints Can't divide by zero!.
- Scenario 3: Input is 1. The program prints Result: 10.0.
Catching Error Messages with "except Exception as e"
- Using
except Exception as e acts as a catch-all for any other errors that were not specifically considered. - This allows the program to capture and print the actual system-generated error message.
- Comprehensive Example:
- Code:
python
try:
number = int(input("Enter a number: "))
result = 10 / number
print("Result:", result)
except ValueError:
print("That's not a number!")
except ZeroDivisionError:
print("Can't divide by zero!")
except Exception as e:
print("Something unexpected happened:", e)
- Examples of Error Message Capture:
- If a variable name is mistyped in the code (e.g.,
results instead of result), the code catches a NameError and prints: name 'results' is not defined.
- If an input is a, it prints: invalid literal for int() with base 10: 'a'.
- If an input is 0, it prints: division by zero.
The finally Clause
- Purpose: The
finally block ensures that certain actions are performed no matter what has happened in the try and except blocks. It always executes. - Example of Behavior:
- Code:
python
try:
a = float(input("Enter first number: "))
b = float(input("Enter second number: "))
print(f"The result is: {a / b}")
except ValueError:
print("Error: Please enter valid numbers.")
finally:
print("Operation attempted.")
- Execution Results:
- Successful run: Input 2 and 1. Output:
The result is: 2.0 followed by Operation attempted..
- Handled Error: Input characters instead of numbers. Output: Error: Please enter valid numbers. followed by Operation attempted..
- Unhandled Error: Input 1 and 0.
- Because ZeroDivisionError is not explicitly handled in the except blocks, the program will crash.
- However, the finally block still executes before the crash.
- Output: Operation attempted. followed by Traceback (most recent call last): ... ZeroDivisionError: float division by zero.
Summary of Exception Handling
- In standard execution, when an error occurs, the program exits immediately (crashes).
- Exceptions allow the program to handle errors gracefully and continue to the subsequent blocks of code.
- The try ~ except structure: Essential for managing runtime errors.
- The finally block: Always executes the code block, regardless of whether an exception was raised or handled.