Lesson 5 of 9
When Python hits something it can't do, it raises an exception and stops. You've seen plenty
already — NameError, TypeError, FileNotFoundError.
The message it prints is a traceback, and it's the single most useful debugging tool you have. Learning to read it properly saves hours.
Reading a traceback
def divide(a, b):
return a / b
def calculate():
return divide(10, 0)
calculate()
That produces roughly:
Traceback (most recent call last):
File "example.py", line 7, in <module>
calculate()
File "example.py", line 5, in calculate
return divide(10, 0)
File "example.py", line 2, in divide
return a / b
ZeroDivisionError: division by zero
Three things to know:
- Read it bottom-up. The last line —
ZeroDivisionError: division by zero— is what actually went wrong. Start there. - The last frame is usually your bug. The lines above show the call chain that led there, most recent last.
- "most recent call last" means exactly that. The top is where execution started; the bottom is where it broke.
Beginners often read the first line and give up. The information you need is at the bottom.
Common exceptions
| Exception | Cause |
| --- | --- |
| SyntaxError | invalid Python — the file won't even start |
| NameError | using a variable that doesn't exist (often a typo) |
| TypeError | wrong type, like "2" + 2 |
| ValueError | right type, bad value, like int("hello") |
| IndexError | list index out of range |
| KeyError | dictionary key not found |
| AttributeError | object has no such attribute or method |
| ZeroDivisionError | divided by zero |
| FileNotFoundError | opening a file that isn't there |
TypeError versus ValueError trips people up. int("hello") is a ValueError — a string is
the right type for int(), but "hello" isn't a valid value. int([]) is a TypeError —
a list is the wrong type entirely.
Exceptions are objects
Every exception is an object with a class, and they form a hierarchy:
print(issubclass(ValueError, Exception))
print(issubclass(FileNotFoundError, OSError))
print(issubclass(ZeroDivisionError, ArithmeticError))
Nearly everything inherits from Exception. That matters for the next lesson: catching
Exception catches almost anything, and catching a specific class catches only that.
Seeing the type at runtime
errors = []
for value in ["10", "abc", "3"]:
try:
errors.append(int(value))
except ValueError as e:
errors.append(type(e).__name__)
print(errors)
type(e).__name__ gives the exception's class name — handy when you're not sure what you're
catching. The next lesson covers try/except properly.
Try it yourself
Trigger three different exceptions and print each one's type and message.
Checkpoint
- An exception stops the program and prints a traceback.
- Read tracebacks bottom-up — the last line names the actual error.
- The frames above show the call chain, most recent last.
ValueErroris a bad value of the right type;TypeErroris the wrong type.- Exceptions are classes in a hierarchy, nearly all under
Exception.
Questions about this lesson
Log in to ask a question.