Course Content
Python Essentials for AI Engineer
6 sections · 48 lessons
What is raise in Python?
What you need to know
Raising with a good message
1def set_temperature(t):2 if not isinstance(t, (int, float)):3 raise TypeError(f"temperature must be a number, got {type(t).__name__}")4 if not 0 <= t <= 2:5 raise ValueError(f"temperature must be between 0 and 2, got {t}")6 return t78for value in [0.7, 5, "hot"]:9 try:10 print(set_temperature(value))11 except (TypeError, ValueError) as e:12 print(type(e).__name__, "-", e)13# 0.714# ValueError - temperature must be between 0 and 2, got 515# TypeError - temperature must be a number, got strPick the built-in type that fits: ValueError for a right type with a bad value, TypeError for the wrong type, KeyError/LookupError for a missing item, NotImplementedError for a method a subclass must provide, RuntimeError for "something went wrong" with no better class. Put the bad value in the message; it saves the reader a debugging session.
Re-raising and chaining
1import json23class ConfigError(Exception):4 pass56def load_config(text):7 try:8 cfg = json.loads(text)9 return cfg["model"]10 except KeyError as err:11 raise ConfigError("config has no 'model' field") from err12 except json.JSONDecodeError:13 print("logging the bad config...")14 raise # same exception, original traceback1516try:17 load_config('{"temperature": 0.2}')18except ConfigError as e:19 print(e, "| cause:", repr(e.__cause__))20# config has no 'model' field | cause: KeyError('model')- Bare
raisere-raises the exception being handled, unchanged. raise X from errsetsX.__cause__, and the traceback shows both, joined by "The above exception was the direct cause of the following exception".- If you raise inside an
exceptwithoutfrom, Python still links them, but the message reads "During handling of the above exception, another exception occurred" — which looks like a bug in your handler.from Nonehides the original when it adds nothing. - Python 3.11+ lets you attach extra context without changing the type:
e.add_note(f"row {i}").
raise vs assert
assert x > 0 raises AssertionError, but asserts are removed when Python runs with -O. Use them for internal "this can't happen" checks, never for validating user input or API data.
A real-life example
A RAG service accepts top_k from a request. A client sends top_k=0. Without validation, the retriever returns an empty list, the prompt has no context, and the LLM answers from its own memory — a confident, ungrounded answer. No error appears anywhere, and the team finds out from a customer complaint.
With a guard at the edge — if top_k < 1: raise ValueError(f"top_k must be at least 1, got {top_k}") — the API returns a clear 400 error at once, and the client fixes their call. Raising early turns a silent quality bug into a visible input bug.
Follow-up questions to expect
- "What is the difference between
raiseandraise e?" — Bareraisere-raises the current exception exactly as it was.raise ealso works in Python 3 but adds the current line to the traceback; bareraiseis the idiom. - "What is exception chaining?" — Linking a new exception to the one that caused it with
raise ... from err, so the traceback shows both. - "Can you raise any object?" — No. Only instances or subclasses of
BaseException;raise "error"is aTypeError.