
Python
Learn the basic pattern for catching and handling exceptions without crashing your program.
The `try-except` block is the simplest way to handle exceptions:
# Basic pattern
try:
# Code that might raise an exception
risky_operation()
except ExceptionType:
# Code that runs if exception occurs
handle_error()
# Example
try:
age = int("not a number")
except ValueError:
print("Please enter a valid number!")
# Program continues after except block
print("Program still running!")Catch only the exceptions you expect and can handle:
# Wrong: catching generic Exception
try:
file = open("data.txt")
lines = file.readlines()
count = int(lines[0]) # Could be ValueError, IndexError, or FileNotFoundError
except Exception:
print("Something went wrong!") # Too vague!
# Better: catch specific exceptions
try:
file = open("data.txt")
lines = file.readlines()
count = int(lines[0])
except FileNotFoundError:
print("File doesn't exist!")
except IndexError:
print("File is empty!")
except ValueError:
print("First line isn't a number!")
# Best: handle each scenario appropriately
try:
with open("data.txt") as file:
first_line = file.readline()
if not first_line:
print("File is empty. Using default.")
else:
count = int(first_line)
print(f"Count: {count}")
except FileNotFoundError:
print("Creating new file...")
with open("data.txt", "w") as f:
f.write("0")
except ValueError:
print("Invalid number format. Using default: 0")Use `as` to get the exception object with details:
# Access exception details
try:
numbers = [1, 2, 3]
print(numbers[10])
except IndexError as e:
print(f"Error type: {type(e).__name__}")
print(f"Error message: {e}")
print(f"Error args: {e.args}")
# Output:
# Error type: IndexError
# Error message: list index out of range
# Error args: ('list index out of range',)
# Practical example: validating user input
def get_positive_integer(prompt):
try:
value = int(input(prompt))
if value <= 0:
print("Please enter a positive number!")
return None
return value
except ValueError as e:
print(f"Invalid input: {e}")
return None
# Test it
age = get_positive_integer("Enter your age: ")Handle different exceptions with different logic:
# Processing a data file
def process_user_file(filename):
try:
with open(filename) as f:
data = json.load(f)
age = int(data["age"])
email = data["email"]
return {
"age": age,
"email": email,
"valid": True
}
except FileNotFoundError:
print(f"File '{filename}' not found. Creating default...")
return {"valid": False, "error": "file_missing"}
except json.JSONDecodeError:
print(f"'{filename}' contains invalid JSON.")
return {"valid": False, "error": "invalid_json"}
except KeyError as e:
print(f"Missing required field: {e}")
return {"valid": False, "error": "missing_field"}
except ValueError:
print("Age field must be a number!")
return {"valid": False, "error": "invalid_age"}
# Test with different scenarios
result = process_user_file("user.json")
print(result)When you want the same handling for multiple exceptions:
# Option 1: Tuple of exceptions
try:
user_input = input("Enter a number: ")
number = int(user_input)
result = 100 / number
print(f"Result: {result}")
except (ValueError, ZeroDivisionError):
print("Invalid input or cannot divide by zero!")
# Option 2: Catch parent exception
try:
user_input = input("Enter a number: ")
number = int(user_input)
result = 100 / number
except ArithmeticError: # Parent of ZeroDivisionError
print("Math error!")
except ValueError:
print("Invalid number format!")
# Option 3: Handle and re-examine
try:
data = {"name": "Alice", "age": 25}
age = int(data.get("age", "0"))
except (ValueError, TypeError):
print("Age must be a valid number!")
age = 0# Example 1: Safe list access
def get_item_safe(items, index, default=None):
try:
return items[index]
except (IndexError, TypeError):
print(f"Cannot access index {index}")
return default
print(get_item_safe([1, 2, 3], 1)) # Returns 2
print(get_item_safe([1, 2, 3], 10)) # Returns None
print(get_item_safe("abc", 0)) # Returns 'a' (strings are indexable)
# Example 2: Safe dictionary access (though dict.get() is better)
def get_value_safe(dictionary, key, default=None):
try:
return dictionary[key]
except KeyError:
print(f"Key '{key}' not found")
return default
user = {"name": "Bob", "age": 30}
print(get_value_safe(user, "name")) # Returns "Bob"
print(get_value_safe(user, "email")) # Returns None
# Example 3: API call with error handling
def fetch_data(url):
try:
response = requests.get(url, timeout=5)
return response.json()
except requests.ConnectionError:
print("Network error. Check your connection.")
return None
except requests.Timeout:
print("Request timed out. Server took too long.")
return None
except ValueError:
print("Response isn't valid JSON.")
return None
# Example 4: Safe type conversion
def to_integer(value):
try:
return int(value)
except (ValueError, TypeError):
print(f"Cannot convert {value} to integer")
return None
print(to_integer("42")) # Returns 42
print(to_integer(3.14)) # Returns 3
print(to_integer("abc")) # Returns None# ❌ Mistake 1: Too broad exception catching
try:
result = 10 / 0
except: # Catches EVERYTHING, even system exits!
print("Error occurred")
# ✅ Better: catch specific exceptions
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero!")
# ❌ Mistake 2: Ignoring exceptions silently
try:
file = open("important.txt")
except:
pass # Silent failure - you won't know it failed!
# ✅ Better: log or handle appropriately
try:
file = open("important.txt")
except FileNotFoundError:
print("File not found. Please check the path.")
file = None
# ❌ Mistake 3: Not using exception information
try:
number = int("abc")
except ValueError as e:
print("Error!") # What error? Can't tell!
# ✅ Better: use the exception info
try:
number = int("abc")
except ValueError as e:
print(f"Cannot convert to integer: {e}")Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward