Module 8: Error Handling and Debugging
Making Code More Robust — Handling Exceptions Gracefully
Module Overview
Errors are inevitable when programming. Files don't exist, data formats are incorrect, network requests fail... How can we make programs handle errors gracefully instead of crashing? This module teaches you Python's exception handling mechanisms and how to debug code to find and fix bugs.
Important Note: Beginners often fear errors, but error messages are your best teacher! Learn to read error messages, and you'll master the key to rapid debugging.
Learning Objectives
After completing this module, you will be able to:
- Understand common Python error types
- Use
try-exceptto catch and handle exceptions - Write robust file reading and data processing code
- Use
finallyandelseclauses - Create custom exception classes
- Master debugging techniques (print, breakpoints, pdb)
- Read and understand error traceback information
Module Contents
01 - Error Types
Core Question: What are Python's common errors?
Core Content:
- Syntax Errors vs Runtime Exceptions:
- Syntax errors: Code is written incorrectly and cannot run (indentation errors, missing colons)
- Runtime exceptions: Code can run but errors occur during execution
- Common Runtime Exceptions:
NameError: Undefined variablepythonprint(age) # NameError: name 'age' is not definedTypeError: Type errorpythonresult = "25" + 5 # TypeError: can only concatenate strValueError: Value errorpythonint("abc") # ValueError: invalid literal for int()KeyError: Dictionary key doesn't existpythondata = {'age': 25} print(data['income']) # KeyError: 'income'IndexError: Index out of rangepythonlist = [1, 2, 3] print(list[10]) # IndexError: list index out of rangeFileNotFoundError: File doesn't existpythonwith open('missing.txt', 'r') as f: # FileNotFoundError content = f.read()ZeroDivisionError: Division by zeropythonresult = 10 / 0 # ZeroDivisionError: division by zero
Practical Application:
# Common errors in data analysis
import pandas as pd
# 1. File doesn't exist
df = pd.read_csv('data.csv') # FileNotFoundError
# 2. Column name error
mean_income = df['income'].mean() # KeyError: 'income'
# 3. Type conversion error
age = int(df['age'][0]) # ValueError: invalid literal02 - Try-Except Exception Handling
Core Question: How to catch and handle errors?
Core Content:
- Basic Syntax:python
try: # Code that might error result = 10 / 0 except ZeroDivisionError: # Error handling print("Cannot divide by zero!") - Catching Multiple Exceptions:python
try: value = int(input("Enter a number: ")) result = 10 / value except ValueError: print("Input is not a number") except ZeroDivisionError: print("Cannot divide by zero") except Exception as e: print(f"Other error: {e}") - else and finally Clauses:python
try: file = open('data.txt', 'r') content = file.read() except FileNotFoundError: print("File doesn't exist") else: print("File read successfully") # Executes if no error finally: file.close() # Always executes - Raising Exceptions:python
def calculate_income(hours, rate): if hours < 0: raise ValueError("Hours cannot be negative") return hours * rate
Practical Application:
# Robust data reading
import pandas as pd
def safe_read_csv(file_path, default_value=None):
"""Safely read CSV file"""
try:
df = pd.read_csv(file_path)
print(f"Successfully read {len(df)} rows")
return df
except FileNotFoundError:
print(f"Error: File {file_path} doesn't exist")
return default_value
except pd.errors.EmptyDataError:
print(f"Error: File {file_path} is empty")
return default_value
except Exception as e:
print(f"Unknown error: {e}")
return default_value
# Usage
df = safe_read_csv('survey.csv')
if df is not None:
# Continue analysis...
pass03 - Debugging Tips
Core Question: How to find and fix bugs?
Core Content:
- Reading Error Traceback:python
Traceback (most recent call last): File "script.py", line 15, in <module> result = calculate_mean(data) File "script.py", line 8, in calculate_mean return sum(data) / len(data) ZeroDivisionError: division by zero- Read from bottom to top: last line is the error type
- Middle shows the call stack: which file, which line, which function
- Print Debugging:python
def process_data(data): print(f"[DEBUG] Input data: {data}") # Check input cleaned = [x for x in data if x > 0] print(f"[DEBUG] After cleaning: {cleaned}") # Check intermediate result return sum(cleaned) / len(cleaned) - Using pdb Debugger:python
import pdb def calculate_mean(data): pdb.set_trace() # Breakpoint return sum(data) / len(data) - Jupyter Magic Commands:python
%debug # Enter debug mode for most recent error %%time # Measure code execution time %pdb on # Automatically enter debug mode - Common Debugging Strategies:
- Binary search: Comment out half the code, find error section
- Simplify input: Test with simplest data
- Unit tests: Write small test cases
Practical Application:
# Case: Debugging data cleaning function
import pandas as pd
def clean_survey_data(df):
"""Clean survey data"""
print(f"[DEBUG] Original data: {len(df)} rows, {len(df.columns)} columns")
# Remove missing values
df_clean = df.dropna(subset=['age', 'income'])
print(f"[DEBUG] After removing NaN: {len(df_clean)} rows")
# Filter ages
df_clean = df_clean[(df_clean['age'] >= 18) & (df_clean['age'] <= 100)]
print(f"[DEBUG] After age filtering: {len(df_clean)} rows")
# Remove anomalous income
df_clean = df_clean[df_clean['income'] > 0]
print(f"[DEBUG] After removing anomalous income: {len(df_clean)} rows")
return df_cleanError Handling Strategy Comparison
| Strategy | Advantages | Disadvantages | Use Cases |
|---|---|---|---|
| No Handling | Simple | Program crashes | Exploratory analysis, Jupyter |
| try-except | Robust | Code verbose | Production code, batch processing |
| Default Value | Elegant | May hide issues | Optional parameters, config reading |
| Logging | Traceable | Requires extra code | Production environment, long-term projects |
How to Learn This Module?
Learning Path
Day 1 (2 hours): Error Types
- Read 01 - Error Types
- Recognize common errors
- Learn to read error messages
Day 2 (3 hours): Try-Except
- Read 02 - Try-Except
- Practice catching exceptions
- Write robust file reading code
Day 3 (2 hours): Debugging Tips
- Read 03 - Debugging Tips
- Use print debugging
- Try pdb debugger
Total Time: 7 hours (1 week)
Minimized Learning Path
For beginners, priority is as follows:
Must Learn (Foundation skills, 4 hours):
- 01 - Error Types (recognize common errors)
- 02 - Try-Except (basic syntax)
- Reading error messages techniques
Important (Advanced skills, 3 hours):
- else and finally clauses
- Print debugging
- Jupyter debugging techniques
Optional (Advanced topics):
- pdb debugger
- Custom exception classes
- Logging (logging module)
Learning Suggestions
Don't Fear Errors
- Errors are learning opportunities
- Each error teaches you a new concept
- Professional programmers encounter many errors too
Learn to Read Error Messages
python# Error message example Traceback (most recent call last): File "script.py", line 15, in <module> # ← Start reading here result = calculate_mean(data) File "script.py", line 8, in calculate_mean return sum(data) / len(data) # ← This line has error ZeroDivisionError: division by zero # ← This is the error type # Interpretation: # 1. Error type: ZeroDivisionError # 2. Error location: script.py line 8 # 3. Reason: Division by zero (len(data) = 0)Progressive Error Handling
python# Stage 1: No handling (exploratory analysis) df = pd.read_csv('data.csv') # Stage 2: Simple handling (scripting) try: df = pd.read_csv('data.csv') except FileNotFoundError: print("File doesn't exist") # Stage 3: Complete handling (production code) def safe_read_csv(file_path): try: df = pd.read_csv(file_path) logger.info(f"Successfully read {len(df)} rows") return df except FileNotFoundError: logger.error(f"File doesn't exist: {file_path}") return None except Exception as e: logger.error(f"Unknown error: {e}") raiseError Handling Patterns for Common Scenarios
python# Pattern 1: File reading try: df = pd.read_csv('data.csv') except FileNotFoundError: df = pd.DataFrame() # Return empty DataFrame # Pattern 2: Dictionary access value = data.get('key', default_value) # More elegant # Rather than try: value = data['key'] except KeyError: value = default_value # Pattern 3: Type conversion try: age = int(user_input) except ValueError: age = None # Or prompt user again
Common Questions
Q: When should I use try-except? A:
- Must use: File operations, network requests, user input, type conversions
- Can use: Data validation, optional features
- Not recommended: Logic errors, algorithm bugs (should fix, not hide)
Q: Why not recommend using except Exception? A: Too broad, will catch all exceptions (including ones you don't want to catch). Should specify exception types.
# Not recommended
try:
result = 10 / x
except Exception: # Too broad
pass
# Recommended
try:
result = 10 / x
except ZeroDivisionError: # Specific
result = 0Q: How to debug in Jupyter? A:
# Method 1: After cell throws error
%debug # Enter debug mode
# Method 2: Automatic debugging
%pdb on # All errors after this auto-enter debug
# Method 3: Set breakpoint in code
import pdb; pdb.set_trace()Q: Print debugging vs pdb debugging? A:
- Print: Simple, fast, suitable for beginners
- pdb: Powerful, interactive, suitable for complex bugs
Q: Will error handling slow down code? A:
tryblock has almost no performance overhead- Only slows when exceptions are raised
- Don't use exceptions to control normal flow
Next Steps
After completing this module, you will have mastered:
- Recognizing and handling common Python errors
- Using try-except to write robust code
- Mastering debugging techniques to quickly locate bugs
- Reading error traceback information
In Module 9, we'll dive into Data Science Core Libraries (NumPy, Pandas, Matplotlib), core skills for data analysis!
In Module 10, we'll learn Machine Learning and LLM APIs, exploring cutting-edge Python applications.
Errors aren't scary—learning to handle and debug is key! Keep going!