Contact
Evil Genius SocietyHomeLearnForumLeaderboardSocialsMessages
← Back to module

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:

  1. Read it bottom-up. The last line — ZeroDivisionError: division by zero — is what actually went wrong. Start there.
  2. The last frame is usually your bug. The lines above show the call chain that led there, most recent last.
  3. "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.
  • ValueError is a bad value of the right type; TypeError is the wrong type.
  • Exceptions are classes in a hierarchy, nearly all under Exception.

Questions about this lesson

Log in to ask a question.