
Python
Learn how to intentionally raise exceptions to enforce rules and signal problems in your functions.
You can deliberately raise exceptions using the `raise` keyword:
# Raise a built-in exception
def get_age(age_input):
try:
age = int(age_input)
except ValueError:
raise ValueError("Age must be a valid number")
# Test it
try:
age = get_age("not a number")
except ValueError as e:
print(f"Caught error: {e}")
# Output: Caught error: Age must be a numberA common use case is validating function parameters:
# Validate age range
def create_student(name, age):
# Check inputs
if not isinstance(name, str):
raise TypeError("Name must be a string")
if not isinstance(age, int):
raise TypeError("Age must be an integer")
if age < 5:
raise ValueError("Age must be at least 5")
if age > 120:
raise ValueError("Age seems unrealistic")
if len(name) == 0:
raise ValueError("Name cannot be empty")
return {"name": name, "age": age}
# Valid input
try:
student = create_student("Alice", 15)
print(f"Created: {student}")
except (TypeError, ValueError) as e:
print(f"Error: {e}")
# Invalid inputs
try:
create_student(123, 15) # TypeError: Name must be a string
except (TypeError, ValueError) as e:
print(f"Error: {e}")
try:
create_student("Bob", 3) # ValueError: Age must be at least 5
except (TypeError, ValueError) as e:
print(f"Error: {e}")Sometimes you catch an exception, do something, then raise it again:
# Logging then re-raising
def process_file(filename):
try:
with open(filename) as f:
return f.read()
except FileNotFoundError as e:
print(f"Warning: {filename} not found!")
raise # Re-raise the same exception
# The caller must handle it
try:
content = process_file("missing.txt")
except FileNotFoundError:
print("Could not read file, using default content")
# Different example: wrap and re-raise
def database_query(query):
try:
# Simulate database call
if "DROP" in query:
raise RuntimeError("Dangerous query!")
except RuntimeError as e:
print(f"Query rejected: {e}")
raise # Let caller know it failed
# Caller can catch it
try:
database_query("DROP TABLE users")
except RuntimeError:
print("Database error occurred")# Bank account withdrawal
def withdraw(balance, amount):
if amount < 0:
raise ValueError("Cannot withdraw negative amount")
if amount == 0:
raise ValueError("Must withdraw at least 1 cent")
if amount > balance:
raise ValueError(f"Insufficient funds. Balance: ${balance}")
return balance - amount
# Test different scenarios
balance = 100.00
try:
balance = withdraw(balance, 30)
print(f"New balance: ${balance}")
except ValueError as e:
print(f"Withdrawal failed: {e}")
try:
balance = withdraw(balance, -10)
except ValueError as e:
print(f"Withdrawal failed: {e}")
try:
balance = withdraw(balance, 200)
except ValueError as e:
print(f"Withdrawal failed: {e}")# Example 1: Email validation
def validate_email(email):
if not isinstance(email, str):
raise TypeError("Email must be a string")
if "@" not in email:
raise ValueError("Email must contain @")
if email.count("@") > 1:
raise ValueError("Email can only have one @")
if "." not in email.split("@")[1]:
raise ValueError("Domain must contain a dot")
return True
try:
validate_email("alice@example.com")
print("Email is valid!")
except (TypeError, ValueError) as e:
print(f"Invalid email: {e}")
try:
validate_email("invalid.email")
except ValueError as e:
print(f"Invalid email: {e}")
# Example 2: Password validation
def validate_password(password):
if len(password) < 8:
raise ValueError("Password must be at least 8 characters")
if not any(c.isupper() for c in password):
raise ValueError("Password must contain uppercase letter")
if not any(c.isdigit() for c in password):
raise ValueError("Password must contain a digit")
return True
try:
validate_password("Weak123")
print("Password is valid!")
except ValueError as e:
print(f"Password error: {e}")
# Example 3: Safe division with custom error
def safe_divide(a, b):
if not isinstance(a, (int, float)):
raise TypeError(f"First argument must be number, got {type(a).__name__}")
if not isinstance(b, (int, float)):
raise TypeError(f"Second argument must be number, got {type(b).__name__}")
if b == 0:
raise ZeroDivisionError("Cannot divide by zero")
return a / b
try:
result = safe_divide(10, 2)
print(f"Result: {result}")
except (TypeError, ZeroDivisionError) as e:
print(f"Calculation error: {e}")
try:
result = safe_divide(10, "five")
except TypeError as e:
print(f"Type error: {e}")# ❌ Unhelpful error message
def bad_validate(age):
if age < 0:
raise ValueError("Error") # What error?
# ✅ Helpful error message
def good_validate(age):
if age < 0:
raise ValueError(f"Age cannot be negative. Got: {age}")
if age > 150:
raise ValueError(f"Age seems unrealistic. Got: {age}")
return True
# Good practice: include context
def validate_score(score, max_score):
if not isinstance(score, (int, float)):
raise TypeError(f"Score must be number, got {type(score).__name__}")
if score < 0:
raise ValueError(f"Score cannot be negative. Got {score}")
if score > max_score:
raise ValueError(
f"Score {score} exceeds maximum of {max_score}"
)
return True
try:
validate_score(105, 100)
except ValueError as e:
print(f"Score validation failed: {e}")Raise exceptions when:
Don't raise exceptions for:
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