Raising exceptions — raise, custom exception classes
WHY do we raise at all?
The core trade-off (this is the 80/20 idea):
- Return a value when there's a meaningful result (including "not found" sometimes).
- Raise an exception when continuing would be a bug or invalid state.
WHAT is raise?
raise ValueError("amount must be positive") # instance created from class + message
raise ValueError # class — Python instantiates it with no argsHOW does it flow? (derive the mechanism from scratch)
When raise runs, Python does, step by step:
- Build the exception object (if you gave a class, call it).
- Attach a traceback recording where we are right now.
- Abandon the current line; look outward for an
exceptthat matches. - Check enclosing
tryblocks in this function. None? Pop this frame. - Repeat in the caller's frame... up and up.
- If nobody catches it, it reaches the top → program prints the traceback and exits.
Custom Exception Classes — WHY make your own?
class InsufficientFundsError(Exception):
"""Raised when a withdrawal exceeds the balance."""
passDeriving a richer custom exception (carry data!)
Sometimes the handler needs facts, not just a name. Add an __init__:

raise with no arguments — re-raising
raise ... from ... — exception chaining
Common Mistakes (Steel-man + fix)
Active Recall
Recall What is the difference between
raise ValueError and raise ValueError("x")?
The first passes the class; Python instantiates it with no message. The second passes an instance with the message stored in .args. Both work.
Recall Which class should custom exceptions inherit from, and why not
BaseException?
Inherit from Exception. BaseException also covers SystemExit/KeyboardInterrupt, which shouldn't be swept up by ordinary error handling.
Recall What does a bare
raise inside an except do?
Re-raises the current exception with its original traceback intact.
Recall What does
raise B from A accomplish?
Sets B.__cause__ = A, chaining the exceptions so the traceback shows the original as the direct cause.
Recall Feynman: explain to a 12-year-old
Imagine you're a waiter taking an order. Normally you bring back food (a return value). But if the kitchen is on fire, you can't bring food — instead you run out yelling "FIRE!" (that's raise). Whoever hears you (an except) can decide what to do: call 911, or yell even louder so the manager upstairs hears (re-raise). A custom exception is like having different specific shouts: "FIRE!", "OUT OF PIZZA!", "WE'RE CLOSED!" — so listeners know exactly which problem to handle.
Connections
- Try-Except-Finally — how raised exceptions get caught
- Exception Hierarchy & BaseException — what you're inheriting from
- Classes and __init__ — building the custom exception's constructor
- Logging in Python — the log-and-re-raise pattern
- assert statement — a lighter cousin that raises
AssertionError
What statement throws an exception in Python?
raise (followed by an exception instance or class)What base class should custom exceptions inherit from?
ExceptionWhy not inherit from BaseException?
SystemExit/KeyboardInterrupt, which shouldn't be caught by normal handlersWhat does a bare raise (no args) do inside except?
What does raise B from A do?
B.__cause__ = A so the cause is shownWhere is the message of an exception stored?
.args tuple, set via super().__init__(msg)Difference between raise ValueError and raise ValueError("x")?
Why raise instead of returning an error code?
What happens if no except ever catches a raised exception?
What method must a data-carrying custom exception call, and why?
super().__init__(message) — to populate .args so str(e) prints correctlyConcept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Dekho, normal function toh ek value return karta hai — jaise jawab dena. Lekin kabhi kabhi sahi jawab dena hi possible nahi hota. Jaise int("hello") — isme number hai hi nahi return karne ko. Aise time pe Python ek galat jhootha jawab dene ke bajaye exception raise kar deta hai, matlab zor se cheekh ke bolta hai "yahan problem hai!". raise keyword tumhare apne code ko bhi aise cheekhne ki power deta hai jab koi invalid cheez detect ho.
raise ValueError("amount must be positive") likho, toh current line chhod ke Python upar ki taraf — caller ke paas, uske caller ke paas — ek matching except dhoondhta hai. Mil gaya toh handle, nahi mila toh program crash ho jaata hai with traceback. Yaad rakho: sirf exception object banana (make) kaafi nahi — return ValueError(...) galti hai. Usko raise karna padta hai, tabhi woh actually phekta hai.
Custom exception banane ka faayda yeh hai ki error ka ek naam ho jaata hai, jiska matlab clear ho. class InsufficientFundsError(Exception): pass — bas itna. Hamesha Exception se inherit karo, BaseException se kabhi nahi (warna Ctrl-C jaise signals bhi fas jaate hain). Agar exception ke saath data bhejna ho (jaise balance, shortfall), toh __init__ likho aur andar super().__init__(message) zaroor call karo — warna print(e) khaali aayega.
Do aur cheezein: andar except mein akela raise likho toh wahi exception dobara aage bhej deta hai (log karke). Aur raise NayaError(...) from purana_error se dono errors chain ho jaate hain — traceback mein asli cause dikhta rehta hai. Bas itna 80/20 yaad rakho aur tum exceptions ke master ho.