Lesson 07
Custom Exceptions and raise — Project-Specific Error Classes
Create custom exception classes inheriting Exception, trigger them with raise, and enforce business rules like invalid PINs, login failures, and insufficient balance.
Big idea: Built-in exceptions solve Python problems. Custom exceptions solve your project's business rules.
What you will master
- Built-in vs custom exceptions
- Create exception classes using inheritance
- Trigger exceptions using
raise - Handle business rules with
try/except - Real enterprise examples (ATM, login, banking)
The complete picture
Easy comparison
| Feature | Built-in | Custom |
|---|---|---|
| Created by | Python | Developer |
| Purpose | Universal errors | Business rules |
| Example | ValueError |
PINError |
| Uses raise? | Usually automatic | Yes — you trigger it |
1. When do we create custom exceptions?
Imagine you are building an ATM. Python does not know what an invalid PIN means. That is your business rule.
These are not Python language errors. They are project-specific rules you model with custom exception classes.
2. The 3 steps to create a custom exception
Step 1 — Choose a meaningful name
PINError
LoginError
BalanceError
ProductErrorUse names that describe the business rule. Convention: end with Error.
Step 2 — Inherit Exception
class PINError(Exception):
pass| Part | Meaning |
|---|---|
class |
Create a new class |
PINError |
Your exception name |
(Exception) |
Inherits Python's exception system |
pass |
No extra code needed — type identification only |
What does inheritance mean?
Step 3 — Save in errors.py
Professional projects keep custom exceptions in one file.
# errors.py
class LoginError(Exception):
pass
class PINError(Exception):
pass
class BalanceError(Exception):
passTypical project structure
This keeps your project organized and makes except blocks easy to read.
3. Understanding raise
raise means:
"Stop normal execution and create this exception."
- PVM raises built-in exceptions implicitly when code fails
- You use
raiseexplicitly for custom business rules
4. ATM PIN example
A simple real-world business rule.
class PINError(Exception):
pass
def verify_pin(pin):
if pin != 1234:
raise PINError("Incorrect PIN")
return "Access Granted"Correct PIN:
print(verify_pin(1234))Output: Access Granted
Wrong PIN:
verify_pin(5555) # raises PINError: Incorrect PINWrap in try/except to show a friendly message instead of a traceback.
5. Interactive banking simulator
Try withdrawing money. If the withdrawal exceeds the balance, BalanceError is raised.
class BalanceError(Exception):
pass
def withdraw(balance, amount):
if amount > balance:
raise BalanceError("Insufficient balance")
return balance - amount
# Success: withdraw(1000, 500) → 500
# Failure: withdraw(1000, 1500) → BalanceErrorChange amount in the playground to test both paths.
6. How raise creates an object
Remember from Lesson 3: exceptions are objects. raise creates that object.
raise BalanceError("Insufficient balance")7. Login system case study
Enterprise applications use custom exceptions everywhere.
class LoginError(Exception):
pass
def login(username, password):
if username != "admin":
raise LoginError("Invalid username")
if password != "1234":
raise LoginError("Invalid password")
return "Login Successful"User flow
The exception clearly represents the business rule, not a generic Python error.
8. Complete example with try, raise, else, finally
This combines everything you learned in Module 15.
class BalanceError(Exception):
pass
def withdraw(balance, amount):
if amount > balance:
raise BalanceError("Amount exceeds balance")
return balance - amount
try:
new_balance = withdraw(1000, 500)
except BalanceError as err:
print("Friendly:", err)
else:
print("Withdraw successful:", new_balance)
finally:
print("Transaction finished")Execution order
Success output:
Withdraw successful: 500
Transaction finishedFailure output (change amount to 1500):
Friendly: Amount exceeds balance
Transaction finished9. Enterprise examples
| Project | Custom exception |
|---|---|
| ATM | PINError |
| Banking | BalanceError |
| Login portal | LoginError |
| E-commerce | OutOfStockError |
| CRM | LeadValidationError |
| Hospital | PatientNotFoundError |
Naming pattern:
- Ends with
Error - Describes the business rule
- Easy to understand in
except
Memory map — Module 15 complete
This is the complete lifecycle of exception handling in professional Python applications.
Interview questions
Q1. Why do we create custom exceptions?
Answer: To represent business rules that Python does not provide — such as invalid PIN, login failure, or insufficient balance.
Q2. Why inherit from Exception?
Answer: It makes your class part of Python's exception hierarchy, allowing it to be raised and caught by try/except.
Q3. What is the purpose of raise?
Answer: To explicitly trigger an exception when a business condition fails.
Q4. Why is pass used in custom exceptions?
Answer: pass creates a new exception type without adding extra behavior. The class exists for identification and matching in except blocks.
Key takeaways
- Built-in exceptions solve Python language errors
- Custom exceptions solve business rules
- Create them by inheriting from
Exception - Use
raiseto trigger them explicitly - Handle them with
try/exceptfor user-friendly messages
Module 15 completed
You now understand the complete exception handling workflow:
- Runtime errors become exceptions
trymonitors risky coderaisecreates custom exceptionsexceptcatches matching typeselseruns after successfinallyalways performs cleanup
This is the foundation used in professional Python applications, APIs, banking systems, CRM platforms, and enterprise software.
Loading playground…
Check your understanding
Custom exceptions and raise quiz
Custom exception class should inherit:
1 / 10