Python What Error to Raise: Code Examples and Patterns
Practical code snippets showing what error to raise in Python. Copy-paste examples for ValueError, TypeError, AttributeError, and custom exceptions.
Python What Error to Raise: Code Examples and Patterns
Quick reference code snippets showing what error to raise in different Python scenarios. Copy and adapt these examples for your projects.
Input Validation Patterns #
Type Validation - Use TypeError #
def validate_string_input(value, param_name="value"):
"""Validate that input is a string"""
if not isinstance(value, str):
raise TypeError(f"{param_name} must be a string, got {type(value).__name__}")
return value
# Usage examples
try:
validate_string_input(123, "username")
except TypeError as e:
print(f"Type error: {e}")
Value Range Validation - Use ValueError #
def validate_age(age):
"""Validate age is within reasonable range"""
if not isinstance(age, int):
raise TypeError("Age must be an integer")
if age < 0:
raise ValueError("Age cannot be negative")
if age > 150:
raise ValueError("Age cannot exceed 150 years")
return age
# Usage examples
test_ages = [25, -5, 200, "thirty"]
for age in test_ages:
try:
valid_age = validate_age(age)
print(f"Valid age: {valid_age}")
except (TypeError, ValueError) as e:
print(f"Invalid age {age}: {e}")
Object State Validation #
Missing Required Attributes - Use AttributeError #
class UserProfile:
def __init__(self, username):
self.username = username
def get_email(self):
if not hasattr(self, 'email'):
raise AttributeError(f"UserProfile '{self.username}' has no email attribute")
return self.email
def get_full_name(self):
if not hasattr(self, 'first_name') or not hasattr(self, 'last_name'):
raise AttributeError("Both first_name and last_name must be set")
return f"{self.first_name} {self.last_name}"
# Usage examples
user = UserProfile("john_doe")
try:
email = user.get_email()
except AttributeError as e:
print(f"Missing attribute: {e}")
user.email = "[email protected]"
print(f"Email: {user.get_email()}")
Invalid Object State - Use RuntimeError #
class Connection:
def __init__(self):
self.is_connected = False
self.is_authenticated = False
def connect(self):
self.is_connected = True
print("Connected")
def authenticate(self, token):
if not self.is_connected:
raise RuntimeError("Must connect before authenticating")
self.is_authenticated = True
print("Authenticated")
def send_data(self, data):
if not self.is_connected:
raise RuntimeError("Connection not established")
if not self.is_authenticated:
raise RuntimeError("Must authenticate before sending data")
return f"Sent: {data}"
# Usage examples
conn = Connection()
try:
conn.send_data("Hello")
except RuntimeError as e:
print(f"Runtime error: {e}")
# Fix the state
conn.connect()
conn.authenticate("token123")
print(conn.send_data("Hello"))
Collection Access Patterns #
Dictionary Key Access - Use KeyError #
def get_config_value(config, key):
"""Get configuration value with specific error"""
if not isinstance(config, dict):
raise TypeError("Config must be a dictionary")
if key not in config:
raise KeyError(f"Configuration key '{key}' not found. Available keys: {list(config.keys())}")
return config[key]
# Safe dictionary access alternative
def safe_get_config(config, key, default=None):
try:
return get_config_value(config, key)
except KeyError:
return default
# Usage examples
config = {"database_url": "localhost", "port": 5432}
try:
value = get_config_value(config, "api_key")
except KeyError as e:
print(f"Key error: {e}")
# Use safe access
api_key = safe_get_config(config, "api_key", "default_key")
print(f"Using default: {api_key}")
List Index Access - Use IndexError #
def get_list_item_safe(items, index, context="list"):
"""Safe list access with descriptive error"""
if not isinstance(items, (list, tuple)):
raise TypeError(f"Expected list or tuple, got {type(items).__name__}")
if not isinstance(index, int):
raise TypeError("Index must be an integer")
length = len(items)
if index >= length or index < -length:
raise IndexError(
f"Index {index} out of range for {context} of length {length}. "
f"Valid range: {-length} to {length-1}"
)
return items[index]
# Usage examples
numbers = [10, 20, 30]
try:
item = get_list_item_safe(numbers, 5, "numbers list")
except IndexError as e:
print(f"Index error: {e}")
Mathematical Operations #
Division by Zero - Use ZeroDivisionError #
def safe_divide(numerator, denominator, precision=2):
"""Safe division with specific error handling"""
if not isinstance(numerator, (int, float)):
raise TypeError(f"Numerator must be a number, got {type(numerator).__name__}")
if not isinstance(denominator, (int, float)):
raise TypeError(f"Denominator must be a number, got {type(denominator).__name__}")
if denominator == 0:
raise ZeroDivisionError("Cannot divide by zero")
result = numerator / denominator
return round(result, precision)
# Usage examples
test_cases = [(10, 2), (15, 0), ("10", 2)]
for num, den in test_cases:
try:
result = safe_divide(num, den)
print(f"{num} / {den} = {result}")
except (TypeError, ZeroDivisionError) as e:
print(f"Error dividing {num} by {den}: {e}")
Invalid Mathematical Operations - Use ValueError #
import math
def safe_sqrt(number):
"""Safe square root calculation"""
if not isinstance(number, (int, float)):
raise TypeError(f"Number must be int or float, got {type(number).__name__}")
if number < 0:
raise ValueError(f"Cannot calculate square root of negative number: {number}")
return math.sqrt(number)
def safe_log(number, base=math.e):
"""Safe logarithm calculation"""
if not isinstance(number, (int, float)):
raise TypeError("Number must be int or float")
if number <= 0:
raise ValueError(f"Logarithm undefined for non-positive numbers: {number}")
if base <= 0 or base == 1:
raise ValueError(f"Invalid logarithm base: {base}")
return math.log(number, base)
# Usage examples
try:
result = safe_sqrt(-4)
except ValueError as e:
print(f"Math error: {e}")
try:
result = safe_log(0)
except ValueError as e:
print(f"Math error: {e}")
Custom Exception Patterns #
Domain-Specific Exceptions #
# Base exception class
class PaymentError(Exception):
"""Base exception for payment operations"""
pass
# Specific payment exceptions
class InsufficientFundsError(PaymentError):
def __init__(self, required, available):
self.required = required
self.available = available
super().__init__(f"Insufficient funds: need ${required}, have ${available}")
class InvalidPaymentMethodError(PaymentError):
def __init__(self, method):
self.method = method
super().__init__(f"Invalid payment method: {method}")
class PaymentProcessingError(PaymentError):
def __init__(self, transaction_id, reason):
self.transaction_id = transaction_id
self.reason = reason
super().__init__(f"Payment {transaction_id} failed: {reason}")
# Payment processor class
class PaymentProcessor:
def __init__(self):
self.valid_methods = ["credit_card", "debit_card", "paypal"]
def process_payment(self, amount, method, account_balance=100):
# Validate payment method
if method not in self.valid_methods:
raise InvalidPaymentMethodError(method)
# Check sufficient funds
if amount > account_balance:
raise InsufficientFundsError(amount, account_balance)
# Simulate processing error
if amount > 1000:
raise PaymentProcessingError("TXN123", "Amount exceeds daily limit")
return f"Payment of ${amount} processed successfully"
# Usage examples
processor = PaymentProcessor()
test_payments = [
(50, "credit_card", 100), # Success
(150, "credit_card", 100), # Insufficient funds
(75, "bitcoin", 100), # Invalid method
(1500, "credit_card", 2000) # Processing error
]
for amount, method, balance in test_payments:
try:
result = processor.process_payment(amount, method, balance)
print(f"✓ {result}")
except InsufficientFundsError as e:
print(f"✗ {e} (need ${e.required - e.available} more)")
except InvalidPaymentMethodError as e:
print(f"✗ {e} (valid methods: {processor.valid_methods})")
except PaymentProcessingError as e:
print(f"✗ {e}")
File Operation Error Patterns #
import os
def safe_file_operation(filename, operation="read", content=None):
"""Safe file operations with specific error handling"""
if not isinstance(filename, str):
raise TypeError("Filename must be a string")
if not filename.strip():
raise ValueError("Filename cannot be empty")
if operation == "read":
try:
with open(filename, 'r') as f:
return f.read()
except FileNotFoundError:
raise FileNotFoundError(f"File '{filename}' does not exist")
except PermissionError:
raise PermissionError(f"No permission to read '{filename}'")
elif operation == "write":
if content is None:
raise ValueError("Content is required for write operation")
try:
with open(filename, 'w') as f:
f.write(content)
return f"Successfully wrote to '{filename}'"
except PermissionError:
raise PermissionError(f"No permission to write to '{filename}'")
else:
raise ValueError(f"Unknown operation '{operation}'. Use 'read' or 'write'")
# Usage examples
try:
content = safe_file_operation("nonexistent.txt", "read")
except FileNotFoundError as e:
print(f"File error: {e}")
try:
result = safe_file_operation("test.txt", "write", "Hello World")
print(result)
except PermissionError as e:
print(f"Permission error: {e}")
Quick Reference Guide #
| Scenario | Error Type | Usage |
|---|---|---|
| Wrong data type | TypeError | isinstance() checks fail |
| Right type, wrong value | ValueError | Valid type but invalid value |
| Missing attribute/method | AttributeError | hasattr() checks fail |
| Missing dictionary key | KeyError | Key not in dictionary |
| Invalid list/tuple index | IndexError | Index out of bounds |
| Invalid runtime state | RuntimeError | Object in wrong state |
| Method not implemented | NotImplementedError | Abstract method placeholders |
| Division by zero | ZeroDivisionError | Mathematical division errors |
| Domain-specific issues | Custom Exception | Business logic errors |
Usage Tips #
- Be specific: Choose the most appropriate exception type
- Provide context: Include helpful error messages with values
- Chain exceptions: Use
raise ... from ...when catching and re-raising - Document exceptions: List expected exceptions in docstrings
- Test error paths: Write tests for your exception handling
These patterns help you write robust Python code with clear, actionable error messages.