Validate with raise, check assumptions with assert
The first function protects against bad input. The second protects against a bug in our own code.
raise lets your own code signal a problem, raise ... from records the cause, and a small custom exception class gives callers a precise name to catch. add_note (Python 3.11) attaches extra context, and assert is for checking your own assumptions, not user input.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 7 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write class InvalidScore(ValueError): pass and a function grade(score) that raises InvalidScore if the score is not between 0 and 100, otherwise returns "pass" for 40 or more and "fail" below.
Write load_age(data) for a dict like {"age": "x"}. It must raise ValueError("invalid age") chained from the original error when data["age"] is missing or not a number.
Write a function that tries int(text), adds a note with the text when it fails and re-raises. Catch it outside and print the notes.
Explain it without notes
How do you create a custom exception, and why would you rather do that than raise Exception("...")?
Explain the difference between raise X from Y, raising inside an except block without from, and raise X from None.
When is assert appropriate, and when is it a bug waiting to happen?
What does a bare raise do, and where is it legal?
Expected output
age ok: 30
rejected: age must be a whole number >= 0, got -5
rejected: age must be a whole number >= 0, got 'ten'
assertion failed: values must be sorted