Course Content
Python Essentials for AI Engineer
6 sections · 48 lessons
What is an Exception in Python?
What you need to know
Syntax errors vs exceptions
A syntax error means Python cannot even parse the file — a missing colon or bracket. Nothing runs. An exception happens while valid code runs: the code is fine, but a value or a situation is not — a file is missing, a key is absent, a network call times out.
The ones you meet in AI and data work
| Exception | Typical cause |
|---|---|
KeyError | a field missing from a JSON response or dict |
IndexError | results[0] on an empty search result |
ValueError | float("N/A") on a CSV cell |
TypeError | "499" + 1, or calling None |
FileNotFoundError | wrong path to a dataset or model file |
json.JSONDecodeError | an LLM reply that is not valid JSON |
TimeoutError, ConnectionError | network calls to APIs |
ZeroDivisionError | accuracy on an empty test set |
How an exception travels
1def parse_amount(cell):2 return float(cell) # raises here34def total(rows):5 return sum(parse_amount(r) for r in rows)67try:8 total(["499.00", "N/A", "120.50"])9except ValueError as e:10 print(type(e).__name__, "-", e) # ValueError - could not convert string to float: 'N/A'float raised inside parse_amount. That function did not handle it, so it moved up to total, then to the caller, where an except caught it. Without that except, Python prints a traceback: the chain of calls, most recent last. Read it from the bottom: the last line names the exception, and the lines just above show where it happened.
The hierarchy
1print(issubclass(KeyError, LookupError)) # True2print(issubclass(FileNotFoundError, OSError)) # True3print(issubclass(TimeoutError, OSError)) # True4print(issubclass(KeyboardInterrupt, Exception)) # False -> sits beside ExceptionBaseException has a few children that are not errors in the usual sense — KeyboardInterrupt (Ctrl+C) and SystemExit (sys.exit()). Everything else you normally handle lives under Exception. So except Exception catches ordinary errors but still lets Ctrl+C stop the program.
A real-life example
A nightly job sends 10,000 customer messages to an LLM for classification. At row 7,412 one record has no "text" field, row["text"] raises KeyError, and the whole job dies after two hours — and because results were only written at the end, all 7,411 answers are lost.
1rows = [{"id": 1, "text": "refund pending"}, {"id": 2}, {"id": 3, "text": "change UPI PIN"}]2done, failed = [], []3for row in rows:4 try:5 done.append((row["id"], row["text"].upper())) # stands in for the LLM call6 except KeyError as e:7 failed.append((row["id"], f"missing field {e}"))8print(done) # [(1, 'REFUND PENDING'), (3, 'CHANGE UPI PIN')]9print(failed) # [(2, "missing field 'text'")]The fixed job handles errors per row, records the failures for review, and keeps going. It also appends results to a file as it goes, so a crash for any other reason loses minutes of work, not hours.
Follow-up questions to expect
- "What is the difference between an error and an exception?" — In Python, errors are reported as exceptions. A syntax error is detected before running; other errors are exceptions raised at runtime.
- "How do you read a traceback?" — Bottom up: the last line gives the exception type and message; the frames above show the call chain, with the failing line last.
- "What is EAFP?" — "Easier to Ask Forgiveness than Permission": try the operation and handle the exception, rather than checking everything first (LBYL, "Look Before You Leap"). It is the common Python style, and it avoids race conditions like a file disappearing between the check and the open.