Introduction to Programming - Error Handling and Debugging
Introduction to Programming Notes
Introduction
- Instructor: Dr. Shounak Roychowdhury
- Institution: School of Information, University of Texas at Austin
Recap of Previous Lecture
- Review of:
- Functions
- Parameter Passing
- Higher Order Functions
- Lambdas
- Recursion
- Modules
- File I/O
Today's Topic
- Focus: Handling Error Scenarios
- Goals:
- Testing
- Debugging
Error Handling Overview
- Anticipate Error Scenarios: Handle them gracefully to maintain program stability.
Key Concepts in Error Handling
- Errors and Exceptions
- Exception Handling
- Mechanism to manage unexpected events in a program.
- Maintains program flow and prevents crashes.
- Common Causes of Exceptions:
- Invalid User Input
- Code Errors
- Device Failures
- Network Connection Loss
- Insufficient Memory
- Division by Zero
- Inaccessible Files
- Race Conditions in Multi-threaded Systems
Exception Handling Process
- General Flow:
- Set of Statements
- Create an Exception (using
raisestatement) - Exception Handler:
- A sequence of operations that handles the error when it occurs.
- Through this mechanism, program execution can resume post-exception handling.
Terminology in Exception Handling
- Error Type:
- Specific type of exception, e.g.,
ZeroDivisionError,KeyError,TypeError,NameError.
- Specific type of exception, e.g.,
- Traceback:
- Sequence of function calls leading to the error, determining the faulty line.
- Error Message:
- Provides a textual explanation of what went wrong.
Reading Python Errors
- Traceback Analysis:
- Start reading from the bottom (the last line indicates the exact error).
- Identify the problematic line number and file.
- Understand the type of exception for insights into the error's nature.
Categories of Errors
Syntax Errors:
- Errors due to incorrect format in Python statements.
- Detected during translation to machine code before execution.
- Example:
mood = "I"m happy"- Causes
SyntaxError: invalid syntax.
Runtime Errors:
- Errors occur while the program is running (e.g., division by zero, accessing an out-of-bound list index).
- Example:
python 5/0 # raises ZeroDivisionError
Syntax Errors
- Common Causes of Syntax Errors:
- Missing colons in statements.
- Incorrect indentation (leading to
IndentationError). - Mixing tabs and spaces (
TabError).
Runtime Errors
- Examples of runtime errors include:
ZeroDivisionError: Raised during division by zero.IndexError: Occurs when accessing a list index that doesn't exist.NameError: Raised when accessing a variable that hasn't been defined.ValueError: Raised for invalid literal operations (e.g.,int('451.23')).
Exception Handling without Try/Except
- Example Scenario: Division by zero without exception handling results in program termination.
deno = 0
nume = 15
frac = nume/deno # ZeroDivisionError
Using Try/Except Blocks
- Structure:
try:
# code that might raise an exception
except ExceptionType:
# code to handle the exception
- Example:
try:
frac = nume/deno
except ZeroDivisionError:
print("cannot divide by zero")
- Benefits: Prevents program termination due to unhandled exceptions.
Catching Specific Errors
- Ability to handle specific exceptions differently;
Example:
try:
frac = nume/deno
except ZeroDivisionError:
print(f"Cannot divide because deno={deno}")
Nested Try/Except Blocks
- Allows handling exceptions at different levels of the code.
- Example:
try:
try:
frac = nume/deno
except ZeroDivisionError:
print("Inner exception handling")
except Exception:
print("Outer exception handling")
Using Finally Block
- Finally Block: Code that runs after
tryandexceptregardless of success or failure.- Used for cleanup actions (e.g., closing files).
Raising Exceptions
- Create custom error conditions using the
raisestatement. - Example:
if deno == 0:
raise ValueError('Denominator cannot be zero.')
Error Chaining
- Raising another exception in response to another allows keeping the context of the original error.
- Use
raise new_exception from old_exceptionsyntax.
Built-in Errors
- NameError: Accessing an undeclared variable.
- TypeError: Passed an argument of inappropriate type.
- ValueError: Invalid value passed as an argument.
- FileNotFoundError: Attempting to open a non-existent file.
- IndexError: Accessing an index not in a list.
Exception Hierarchy
- Base class:
BaseException - Subcategories include:
ExceptionArithmeticErrorRuntimeErrorOSError
- Hierarchical structure to classify and handle exceptions efficiently.
User-defined Exceptions
- Custom exceptions can extend the
Exceptionclass. - Useful for grouping related error conditions or when standard exceptions aren't sufficient.
Testing and Debugging
- Defensive Programming: Ensure code behaves as expected by checking assumptions and outputs.
Types of Testing
- Unit Testing: Validate individual units (functions) of the program.
- Regression Testing: Check previously fixed bugs.
- Integration Testing: Validate combined parts of the system.
Debugging Techniques
- Use print statements for temporary checks until issues are resolved.
- Leverage tools like Python’s built-in debugger (
pdb). - Follow established debugging procedures to identify bugs systematically.
Assertions
- Assertion Statements: Verify assumptions during code execution. They raise an
AssertionErrorif the condition fails. - Example:
assert len(grades) != 0, 'No grades data.'
Summary
- Always handle exceptions explicitly to maintain control over program flow.
- Keep code modular for easier testing and debugging.
- Leverage Python’s tools for effective debugging.