π¨ Python Custom Exceptions β Creating Your Own Error Types
Introduction π
Python allows you to create your own exceptions, known asCustom Exceptions. These are useful when the built-in exceptions don't describe your error clearly.
Note
π‘ Custom exceptions make your code more readable, structured, and easier to debug.
1. Creating Your First Custom Exception π§±
All custom exceptions must inherit from Exception (or any of its subclasses).
basic_custom_exception.py
class MyError(Exception):
pass
try:
raise MyError("Something went wrong!")
except MyError as e:
print("Caught custom error:", e)β The pass keyword is enough for simple custom exceptions.
2. Adding a Custom Message ποΈ
custom_message.py
class AgeError(Exception):
def __init__(self, message):
super().__init__(message)
def check_age(age):
if age < 0:
raise AgeError("Age cannot be negative!")
try:
check_age(-5)
except AgeError as e:
print("β", e)3. Custom Exception with Additional Attributes π¦
exception_attributes.py
class LoginError(Exception):
def __init__(self, username, message):
self.username = username
super().__init__(message)
try:
raise LoginError("admin", "Invalid password")
except LoginError as e:
print("User:", e.username)
print("Error:", e)Note
β You can store extra data inside custom exceptions.
4. Using Custom Exceptions in Functions π―
function_custom_exception.py
class NegativeNumberError(Exception):
pass
def square_root(n):
if n < 0:
raise NegativeNumberError("Cannot take square root of negative number")
return n ** 0.5
try:
print(square_root(-9))
except NegativeNumberError as e:
print("β", e)5. Creating a Hierarchy of Custom Exceptions π§©
error_hierarchy.py
class AppError(Exception):
pass
class FileError(AppError):
pass
class NetworkError(AppError):
pass
try:
raise NetworkError("Network unreachable")
except NetworkError as e:
print("β", e)
except AppError:
print("General application error")β Hierarchies make large applications more maintainable.
6. Using Custom Exceptions for Validation π
validation_example.py
class EmailError(Exception):
pass
def validate_email(email):
if "@" not in email:
raise EmailError("Invalid email format")
try:
validate_email("hello.com")
except EmailError as e:
print("β", e)7. Raising Built-In Exceptions vs Custom Exceptions βοΈ
| Built-in Exception | Custom Exception |
|---|---|
| Generic error message | Meaningful app-specific message |
| No custom attributes | Can include extra information |
| Good for common errors | Good for domain-specific logic |
8. Real-World Example: Banking System π°
banking_example.py
class InsufficientFundsError(Exception):
pass
def withdraw(balance, amount):
if amount > balance:
raise InsufficientFundsError("Not enough balance")
return balance - amount
try:
print(withdraw(500, 800))
except InsufficientFundsError as e:
print("β", e)9. Real-World Example: Authentication System π
auth_example.py
class UserNotFoundError(Exception):
pass
class WrongPasswordError(Exception):
pass
def login(username, password):
users = {"admin": "123"}
if username not in users:
raise UserNotFoundError("User does not exist")
if users[username] != password:
raise WrongPasswordError("Incorrect password")
return "Login successful!"
try:
print(login("root", "123"))
except UserNotFoundError as e:
print("β", e)
except WrongPasswordError as e:
print("β", e)10. Custom Exceptions in Large Applications π
- β Better debugging and logging
- β Cleaner separation of error types
- β Works well with multi-module projects
- β Helps build professional-grade libraries
11. Best Practices π‘
- β Inherit from Exception, not BaseException
- β Use clear, meaningful names (e.g., AgeError, LoginError)
- β Provide informative messages
- β Group related exceptions using class hierarchy
- β Avoid overusing custom exceptions
Conclusion π
>>βCustom Exceptions let you define meaningful, domain-specific errors β making your applications clean, predictable, and easier to maintain.β β¨
You now fully understand Custom Exceptions in Python! Want the next topic? Try Raising Exceptions, Error Hierarchies, Logging, or File Handling. Just tell me! π