PCAP · Domain 2 of 5

PCAP Domain 2: Exceptions

Section 2 tests how Python reports and handles errors: which except branch runs, when else and finally execute, what raise and assert do, how the built-in hierarchy is shaped, and how to add your own exception classes.

Exam weight
14%
Official objectives
2
Estimated questions estimate
~5
Suggested study time estimate
6–10 hrs

About 10 min read Reviewed October 2026

Overview

Exceptions is Section 2 of the PCAP-31-03 syllabus, with two objectives. Handling errors using Python-defined exceptions covers try and except blocks, the order of except branches, except ... as, grouping several exceptions in one branch, the built-in exception hierarchy, raise with and without an argument, assert, the args property of exception objects, and the else and finally clauses. Extending the exceptions hierarchy covers defining your own exception classes and fitting them into the existing tree so that broader handlers still catch them.

The section is small in objectives but dense in rules. Every item turns on control flow: which branch Python selects, whether a later branch is reachable, and which clauses run after the error is handled. Knowing the parent of each common built-in exception, such as ArithmeticError for ZeroDivisionError and LookupError for IndexError and KeyError, settles many questions before you read the options.

How it's tested

Section 2 items present try statements with two or more except branches, sometimes with else and finally, and ask what is printed. Others show a class hierarchy of custom exceptions and ask which handler catches a raised instance, or what e.args holds. Reading the branches strictly top to bottom is the core habit the exam rewards.

  • First matching branch

    Several except branches could match, and you pick the first one in source order whose class is the raised type or its ancestor.

  • Clause sequencing

    A try block has else and finally, and you decide which clauses run for the error and no-error paths.

  • Custom subclass catch

    A user-defined exception inherits from another, and you identify which handler catches it and what its args contain.

Reasoning it through

A try block runs int('x') and has except Exception first, then except ValueError. int('x') raises ValueError, which is a subclass of Exception, so the first branch matches and handles it. The ValueError branch can never run for this error. Picking the specific handler because it names the exact class is the mistake; Python checks branches in order and stops at the first match.

Objectives 2

Official objectives from the OpenEDG Python Institute outline, in outline order.

2.1 Handle errors using Python-defined exceptionstry/except, branch order, except ... as, grouped exceptions, hierarchy, raise, assert, args, else and finally.
What it means
This objective covers the full handling toolkit for built-in exceptions: catching them, ordering handlers, binding the exception object, grouping exception types, re-raising, assertions, reading args, and running code after success or always.
What to understand
Python tests except branches from top to bottom and runs only the first one that matches the raised class or one of its ancestors. A tuple such as except (TypeError, ValueError) catches either type. except ... as e binds the instance, whose args attribute is a tuple of constructor arguments. A bare raise inside a handler re-raises the current exception. assert condition raises AssertionError when the condition is false. else runs only when the try block raised nothing; finally always runs.
How it shows up
Expect output-prediction items with nested or ordered handlers and questions about whether else or finally executes.
Common confusion
Believing Python searches for the most specific handler; it takes the first matching branch in source order.
2.2 Extend the exceptions hierarchy with self-defined exceptionsDefining custom exceptions and integrating them into existing hierarchies.
What it means
This objective covers creating exception classes by subclassing Exception or a more specific built-in, and arranging them so that handlers for a parent class also catch the children.
What to understand
A custom exception is an ordinary class that inherits from Exception, for example class StockError(Exception): pass. Subclassing a built-in such as ValueError makes existing except ValueError handlers catch your error too. Overriding __init__ and calling super().__init__(message) keeps args and the printed message correct. A handler written for the base custom class catches every subclass raised beneath it, so base-class handlers belong after the specific ones.
How it shows up
Items show a small custom hierarchy and ask which except branch catches a raised subclass instance.
Common confusion
Subclassing BaseException for application errors; that bypasses except Exception handlers, which is rarely intended.

High-yield concepts

The terms, rules and formulas this domain turns into questions most often.

  • Branch order

    Python runs the first except branch that matches the raised exception.

    Remember
    Specific handlers must come before general ones.
    Tested as
    Most output items in this section.
    Trap
    Expecting a later, more specific branch to win.
  • Grouped exceptions

    One except clause can catch several types listed in a tuple.

    Remember
    Parentheses are required: except (A, B):
    Tested as
    Syntax and selection items.
    Trap
    Writing except A, B without parentheses.
  • except ... as e

    Binds the exception instance to a name inside the handler.

    Remember
    The name is removed after the handler ends.
    Tested as
    Questions that print e or e.args.
    Trap
    Using e after the except block.
  • args

    Tuple holding the arguments passed to the exception constructor.

    Remember
    ValueError('a', 1).args is ('a', 1).
    Tested as
    Output items printing e.args.
    Trap
    Expecting a string instead of a tuple.
  • Bare raise

    Re-raises the exception currently being handled.

    Remember
    Valid only while an exception is active.
    Tested as
    Propagation questions.
    Trap
    Thinking it raises a new generic Exception.
  • assert

    Raises AssertionError when its expression is false.

    Remember
    An optional message becomes the args value.
    Tested as
    Questions on which exception appears.
    Trap
    Expecting ValueError or no error.
  • else clause

    Runs only when the try block finishes without raising.

    Remember
    It is skipped whenever an exception occurred.
    Tested as
    Clause sequencing items.
    Trap
    Running else after a handled exception.
  • finally clause

    Runs whether or not an exception occurred.

    Remember
    It runs even if the try block returns.
    Tested as
    Clause sequencing items.
    Trap
    Skipping finally after a return.
  • BaseException vs. Exception

    BaseException is the root; Exception is the parent of most errors.

    Remember
    KeyboardInterrupt and SystemExit sit directly under BaseException.
    Tested as
    Hierarchy questions.
    Trap
    Assuming except Exception catches every error.
  • ArithmeticError

    Parent of ZeroDivisionError, OverflowError and FloatingPointError.

    Remember
    except ArithmeticError catches division by zero.
    Tested as
    Hierarchy and branch order items.
    Trap
    Thinking ZeroDivisionError derives directly from Exception.
  • LookupError

    Parent of IndexError and KeyError.

    Remember
    One LookupError handler covers both.
    Tested as
    Hierarchy questions.
    Trap
    Placing KeyError under ValueError.
  • Custom exception class

    A user-defined class inheriting from Exception or a subclass.

    Remember
    Handlers for any ancestor catch it.
    Tested as
    Custom hierarchy items.
    Trap
    Forgetting that parent handlers catch children.

Side by side

Concepts candidates mix up, compared on the point that decides the answer.

Clauses of a try statement

ConceptMeaningKey differenceCommon trap
try Code that might raise Stops at the first raised exception Assuming later lines in try still run
except Handles a matching exception First match in order wins Expecting several branches to run
else Runs if try raised nothing Skipped after any exception Running it after a handled error
finally Cleanup that always runs Runs on success, error and return Skipping it after return

Raising mechanisms

ConceptMeaningKey differenceCommon trap
raise ValueError('x') Raises a new exception instance args holds ('x',) Thinking args is the string 'x'
raise Re-raises the active exception Only valid inside a handler Using it outside any handler
assert cond, msg Raises AssertionError if cond is false msg becomes args Expecting a different exception type

Common built-in families

ConceptMeaningKey differenceCommon trap
ArithmeticError Math failures Parent of ZeroDivisionError Missing it as a catch-all for division
LookupError Failed index or key lookups Parent of IndexError and KeyError Confusing it with ValueError
BaseException-only System-level signals KeyboardInterrupt and SystemExit Expecting except Exception to catch them

Exam traps

Each trap is an answer that looks right. Learn the clue that should change your mind.

  1. Specific handler wins

    What candidates pick
    Pick the output of the ZeroDivisionError branch when ArithmeticError is listed first.
    Why it looks right
    The exact class name matches the error.
    Why it's wrong
    Python stops at the first matching branch, and ArithmeticError is an ancestor of ZeroDivisionError.

    Clue to watch for A parent class appears above its child in the except list.

  2. else after handling

    What candidates pick
    Include else output after an exception was caught.
    Why it looks right
    The handler resolved the problem.
    Why it's wrong
    else runs only if the try block raised nothing at all.

    Clue to watch for The try block contains an operation that fails.

  3. Return skips finally

    What candidates pick
    Leave out finally output because try returned first.
    Why it looks right
    return normally exits the function immediately.
    Why it's wrong
    finally runs before the function actually returns, even after a return statement.

    Clue to watch for A return sits inside try with a finally clause below.

  4. args is the message

    What candidates pick
    Choose 'error' as the output of print(e.args).
    Why it looks right
    The message looks like the only value.
    Why it's wrong
    args is always a tuple, so the output is ('error',) with the trailing comma.

    Clue to watch for The code prints e.args rather than e.

  5. Tuple without parentheses

    What candidates pick
    Accept except TypeError, ValueError: as valid grouping.
    Why it looks right
    Commas separate items elsewhere in Python.
    Why it's wrong
    Python 3 requires a parenthesized tuple to catch several types in one clause.

    Clue to watch for Options differ only in the presence of parentheses.

  6. Custom error escapes

    What candidates pick
    Say an uncaught error occurs when except Exception follows raise MyError.
    Why it looks right
    MyError is not a built-in type.
    Why it's wrong
    A class derived from Exception is caught by except Exception like any built-in subclass.

    Clue to watch for The custom class definition shows Exception as its base.

Answer framework

For a Section 2 snippet, follow these steps to trace control flow the way PCAP-31-03 expects.

  1. Find the first line in the try block that raises, and name the exact exception class it produces, such as ZeroDivisionError for 1 / 0 or ValueError for int('x').
  2. Walk the except branches from top to bottom and stop at the first whose class is that type or one of its ancestors.
  3. If no branch matches, the exception propagates outward after finally runs, so check enclosing try statements or expect a traceback.
  4. Decide whether else runs: only when the try block raised nothing, never after a handled error.
  5. Add the finally output last, and remember it runs even when the try or handler executes return or raises again.

Practice question

A developer wraps a division in a try statement with two except branches, an else branch and a finally branch. What does this code print? try: x = 1 / 0 except ArithmeticError: print('A') except ZeroDivisionError: print('Z') else: print('E') finally: print('F')

Choose one answer

Want more like this? The PCAP practice test has questions for every domain.

Checklist

0 of 11

Tick each one you can do without notes. Your ticks stay in this browser.

Study strategy

Start by drawing the part of the hierarchy PCAP uses: BaseException at the top, Exception beneath it, then ArithmeticError with ZeroDivisionError, LookupError with IndexError and KeyError, and the standalone ValueError, TypeError and AssertionError. Put KeyboardInterrupt and SystemExit beside Exception, not under it. Keep the drawing next to you while practicing.

Then write small try statements in the interpreter and change one thing at a time: swap the order of handlers, remove the failing line, add a return inside try, add else and finally. Predict the output before running each version. This trains the top-to-bottom reading that the exam rewards.

Move on to raise and assert. Raise built-in exceptions with one, two and zero arguments and print args each time. Re-raise inside a handler with a bare raise and watch the traceback. Trigger an assert with and without a message.

Finish with custom exceptions. Build a base class derived from Exception and two subclasses, raise each, and test which handlers catch them. Then derive one class from ValueError and confirm that an existing ValueError handler catches it.

FAQ

How much of PCAP is Section 2, Exceptions?

Exceptions is 14% of PCAP-31-03, and the official syllabus assigns it 5 of the 40 exam items.

Does Python pick the most specific except branch?

No. It checks branches in the order written and runs the first one whose class matches the exception or one of its ancestors.

When does the else clause run?

Only when the try block completes without raising any exception. A handled exception still means else is skipped.

What is the args property?

A tuple of the arguments passed to the exception's constructor. An exception created with one string has a one-element tuple.

Why should custom exceptions inherit from Exception?

Handlers written as except Exception then catch them, while system signals such as KeyboardInterrupt stay outside that net.

What does a bare raise do?

Inside an except block it re-raises the exception currently being handled, preserving its type and traceback.

Does assert run in every situation?

Normally yes, but assertions are removed when Python runs with the -O optimization flag, so they suit checks during development rather than input validation.

Test your Domain 2 knowledge

You have covered except ordering, else and finally, raise and assert, args and custom exception classes. Test whether you can trace every branch correctly in timed questions.

Keep going