Exceptions
Exception hierarchy, handling, finally, and custom exceptions.
15 questions
JuniorTheoryVery commonWhat is exception handling, and how do you raise an exception?
What is exception handling, and how do you raise an exception?
It's a way to react to errors while the program runs: try/except catches them, raise raises one. You raise an object or a class derived from BaseException, such as ValueError. An uncaught one passes up to the caller.
Common mistakes
- ✗Expecting
raiseto accept any object, such as a string or an int: it accepts only an exception, an instance or a class derived fromBaseException, and gives aTypeErrorfor anything else. - ✗Expecting
raiseto always crash the program: atry/exceptaround the call, even in a calling function, catches the exception, and the program goes on.
Follow-up questions
- →What is the difference between
raise ValueErrorandraise ValueError("bad")? - →What happens if no
exceptanywhere catches the exception?
JuniorTheoryCommonHow do you define a custom exception in Python?
How do you define a custom exception in Python?
Subclass Exception (not BaseException), conventionally naming it with an Error suffix. You may add attributes or a custom __init__ to carry data. Then raise MyError("msg") like any built-in exception.
Common mistakes
- ✗Subclassing
BaseExceptioninstead ofException: anexcept Exceptionbranch then misses your error, because it catches onlyExceptionand its subclasses. - ✗Expecting a custom exception to be a bare marker: like any exception it takes a message,
MyError("msg"), and can carry extra attributes set in its__init__.
Follow-up questions
- →How do you build a hierarchy of related custom exceptions?
- →What should a custom
__init__call onsuper()to preserveargs?
JuniorTheoryCommonWhat does the program print?
What does the program print?
done zero
Open full question →Common mistakes
- ✗Expecting
zero, as ifreturnleft the function at once:finallyruns on the way out oftry, even past areturn, sodoneis printed first. - ✗Expecting
zero done:finallyruns insidecheck, before the function hands back"zero", so the outerprintgets the value only afterdoneis out.
Follow-up questions
- →What does
print(check(5))print? - →Why does
print("done", end=" ")keep both words on one line?
JuniorTheoryCommonWhat does the program print?
What does the program print?
general
Open full question →Common mistakes
- ✗Expecting
value, as if Python picked the most specificexcept: it checks them top to bottom and runs the first that matches, andValueErroris a kind ofException. - ✗Expecting a
SyntaxErrorfor the unreachableexcept ValueError: Python accepts it, but the branch never runs because the one above always catches first.
Follow-up questions
- →How would you reorder the branches so that
valueis printed? - →Which
exceptruns forint(None), and why?
JuniorTheoryCommonWhat is the exception class hierarchy at the top?
What is the exception class hierarchy at the top?
BaseException is the root. Exception derives from it and is the base for ordinary errors. But SystemExit, KeyboardInterrupt, and GeneratorExit derive from BaseException directly, so except Exception does not catch them.
Common mistakes
- ✗Assuming
except ExceptioncatchesSystemExitorKeyboardInterrupt - ✗Treating
BaseExceptionandExceptionas interchangeable
Follow-up questions
- →Why are
SystemExitandKeyboardInterruptdeliberately kept outsideException? - →Which base class should a bare
except:clause be thought of as catching?
JuniorTheoryCommonWhy use try/finally without an except?
Why use try/finally without an except?
The finally block always runs — whether the try succeeds, raises, or returns — so it's used for guaranteed cleanup like closing files or releasing locks, while letting any exception propagate uncaught.
Common mistakes
- ✗Believing
finallyis skipped when thetryraises — it always runs - ✗Thinking
finallyswallows the exception instead of letting it propagate
Follow-up questions
- →What happens if
finallyitself contains areturnorraise? - →How does a
withstatement relate totry/finally?
JuniorTheoryCommonWhat happens when this program runs?
What happens when this program runs?
An IndentationError, and nothing prints
Common mistakes
- ✗Expecting
startto print first: Python checks the indentation of the whole file before it runs, so the error stops it before a single line executes. - ✗Expecting the extra indent to be ignored: an indent opens a block, and a block may start only after a line ending in a colon.
Follow-up questions
- →Which line does the traceback point to, and which of its lines names the error?
- →What prints if the last line is
pritn("end")with no indent?
MiddleTheoryCommonIn what order must multiple except handlers be written?
In what order must multiple except handlers be written?
Handlers are checked top-to-bottom and only the first match runs, so more-specific exceptions must come before their general bases, or the general one shadows them. A bare except: must be last.
Common mistakes
- ✗Placing a general base handler before its specific subclass, shadowing the latter
- ✗Believing multiple matching handlers all run instead of just the first
Follow-up questions
- →How does
except (TypeError, ValueError)differ from two separate clauses? - →Why does Python recommend avoiding a bare
except:clause?
MiddleTheoryOccasionalWhat does the else block of a try statement do?
What does the else block of a try statement do?
The else runs only if the try block completed without raising any exception. It holds code that shouldn't be guarded by the except, keeping the protected try minimal. It runs before finally.
Common mistakes
- ✗Thinking
elseruns when an exception occurred rather than when none did - ✗Confusing
elsewithfinallyand assuming it always runs
Follow-up questions
- →Why move code into
elseinstead of leaving it insidetry? - →In what order do
elseandfinallyexecute on a clean run?
MiddleDebuggingOccasionalWhy is this ValueError handler unreachable?
Why is this ValueError handler unreachable?
except Exception is checked first and catches ValueError too (it is a subclass), so the ValueError handler is unreachable (Python even flags it). Put specific exceptions before general ones. Also avoid a bare except: — it swallows KeyboardInterrupt / SystemExit.
Common mistakes
- ✗Writing the general handler before the specific one
- ✗Thinking Python picks the most specific matching handler regardless of order
- ✗Believing
ValueErroris not a subclass ofException
Follow-up questions
- →What does Python warn about for an unreachable
exceptclause? - →Why is a bare
except:discouraged even when ordering is correct?
MiddleTheoryOccasionalHow do you catch an exception, act, then re-raise the same one?
How do you catch an exception, act, then re-raise the same one?
Use a bare raise with no argument inside the except block — it re-raises the currently handled exception while preserving its original traceback. Writing raise exc instead would reset or alter that traceback.
Common mistakes
- ✗Writing
raise excinstead of a bareraise, which mangles the traceback - ✗Thinking a bare
raiseraises a generic error rather than the current one
Follow-up questions
- →How does
raise NewError from excdiffer from a bareraise? - →What does a bare
raisedo if no exception is currently being handled?
MiddleTheoryOccasionalWhat are warnings, and how do you issue one?
What are warnings, and how do you issue one?
Warnings flag non-fatal issues without stopping execution. Warning is a subclass of Exception; warnings.warn(message, category=UserWarning) emits one. The warnings filter can suppress them or escalate them to errors.
Common mistakes
- ✗Assuming a warning stops execution like an exception does
- ✗Forgetting that
Warningitself derives fromException
Follow-up questions
- →How do you escalate a specific warning category into a hard error?
- →What does the
stacklevelargument ofwarnings.warncontrol?
SeniorTheoryOccasionalWhat is exception chaining (__context__ vs __cause__)?
What is exception chaining (__context__ vs __cause__)?
If an exception is raised while handling another, Python implicitly links the old one in __context__. Explicit raise New from old sets __cause__ for a direct cause; raise New from None suppresses the displayed context.
Common mistakes
- ✗Believing a second exception overwrites and loses the original
- ✗Confusing implicit
__context__with the explicit__cause__fromraise ... from
Follow-up questions
- →When would you deliberately use
raise New from None? - →How does
__suppress_context__change the printed traceback?
SeniorTheoryOccasionalWhat happens to an exception that no handler catches?
What happens to an exception that no handler catches?
It propagates outward to the nearest enclosing try/except; if none catches it, the interpreter prints the traceback to sys.stderr and exits. But SystemExit exits quietly, and one raised in __del__ only prints "Exception ignored".
Common mistakes
- ✗Thinking an uncaught exception is silently ignored and execution continues
- ✗Assuming
SystemExitprints a full traceback like an ordinary error
Follow-up questions
- →How can you customize what happens via
sys.excepthook? - →Why is an exception in
__del__only reported, not propagated?
SeniorTheoryRareWhen can a SyntaxError actually be caught at runtime?
When can a SyntaxError actually be caught at runtime?
A SyntaxError in the main module aborts before execution, so it can't be caught there. It is catchable at runtime: importing a module with bad syntax, or running eval/exec on a malformed string. SyntaxError subclasses Exception.
Common mistakes
- ✗Assuming a
SyntaxErrorcan never be caught under any circumstances - ✗Believing
try/exceptcan skip over malformed syntax in the current file
Follow-up questions
- →Why does the parser fail the whole module before any line runs?
- →What related error does
IndentationErrorsubclass?