Session 12 - Errors & Debugging

Session 12 of the Python Fundamentals series, covered in depth. Its aim is to stop you fearing the red text. It shows how to read a traceback from the bottom up and how to recognize the common errors - NameError, TypeError, ValueError, IndexError, KeyError, ZeroDivisionError, SyntaxError, and IndentationError - along with their exact messages. It then guards risky code with try and except, catches specific error types, captures the message with "as e", and validates input in a loop, before covering how to debug by printing values, reproducing the problem, and narrowing it down. The traps are a bare except that hides bugs, and catching the wrong error type. Every snippet, message, and traceback was copied verbatim from CPython 3.12.

Subject: Python Fundamentals · 95 slides · code lesson

Open the interactive version of this deck · Homework for this lesson

What this lesson covers

The lesson, slide by slide

1. Errors & Debugging

Title

Python Fundamentals - Session 12

Read the message, fix the bug - and stop fearing the red text

2. What you will be able to do

Objectives

Everyone's code breaks. The error message tells you where and why. By the end you can:

  1. Read a traceback from the bottom up.
  2. Recognize NameError, TypeError, ValueError, IndexError, KeyError, and more.
  3. Guard risky code with try / except.
  1. Catch a specific error type and validate input in a loop.
  2. Debug by printing values, reproducing, and narrowing down.
  3. Avoid the bare-except trap.

3. What survived from Session 11 - Strings Toolkit?

Warm-up

Discussion prompt

Before we open Session 12 - Errors & Debugging: without looking back, what was the main idea of Session 11 - Strings Toolkit, and what could you do by the end of it that you could not do before?

Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.

Answer:

That session covers .lower(), .upper(), and .strip(), the in operator with .startswith() and .endswith(), length, indexing, and slicing, .split() and .replace(), f-strings, and the immutability trap.

4. Errors Are Normal

Section

Part 1

5. Everyone's code errors

Concept

Errors are not a sign you are bad at this - they are a normal, constant part of programming for everyone.

The skill is not avoiding errors; it is reading them and fixing them quickly.

6. Break it if you can: Everyone's code errors

Counterexample

Discussion prompt

Errors are not a sign you are bad at this - they are a normal, constant part of programming for everyone.

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

Answer:

The skill is not avoiding errors; it is reading them and fixing them quickly.

7. An error stops and explains

Concept

When Python hits something it cannot do, it stops and prints a traceback - a report of what went wrong and where.

traceback — The error report Python prints when it stops. It shows the chain of calls that led to the error, ending with the error type and message.

8. By analogy: An error stops and explains

Analogy

Discussion prompt

Explain An error stops and explains by analogy to something with no Python Fundamentals in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

When Python hits something it cannot do, it stops and prints a traceback - a report of what went wrong and where.

9. The error is trying to help

Intuition

Treat the red text as a helpful note, not a scolding. It literally tells you the file, the line, and the reason.

Most beginners' real problem is not the bug - it is not reading the message. Slow down and read it.

10. Teach it back: The error is trying to help

Explain it

Discussion prompt

Explain The error is trying to help to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

Treat the red text as a helpful note, not a scolding. It literally tells you the file, the line, and the reason.

11. Reading a Traceback

Section

Part 2

12. Read from the bottom up

Concept

The last line is the most important: it names the error type and the message. Start there.

The lines above trace how Python got there - the most recent call is at the bottom.

13. Predict the next row: Anatomy of a traceback

Pattern

Predict first

The table runs: File ... line 4, in <module> | where it started: the call · File ... line 2, in greet | where it actually failed · return "Hi " + naem | the exact line

In Anatomy of a traceback, given the rows so far: what is the next one — the row where traceback part is NameError: name 'naem' is not defined?

Correct: NameError: name 'naem' is not defined | the type and reason

traceback parttells you
File ... line 4, in <module>where it started: the call
File ... line 2, in greetwhere it actually failed
return "Hi " + naemthe exact line
NameError: name 'naem' is not definedthe type and reason

Why: The relationship between the columns, not the individual numbers, is what generates the next row. It says NameError: name 'naem' is not defined - a typo'd variable.

14. Anatomy of a traceback

Worked example

A misspelled naem inside a function:

def greet(name):
    return "Hi " + naem

print(greet("Sam"))

Read the bottom line first

Why: It says NameError: name 'naem' is not defined - a typo'd variable.

traceback parttells you
File ... line 4, in <module>where it started: the call
File ... line 2, in greetwhere it actually failed
return "Hi " + naemthe exact line
NameError: name 'naem' is not definedthe type and reason

The fix follows from the message

Why: Verified by execution: this is the real traceback. naem should be name; correcting the spelling fixes it.

15. Fill in: tells you for Anatomy of a traceback

Comparison

Comparison matrix

From Anatomy of a traceback: refill the tells you column from what you know. The rest of the table is as it appeared.

traceback parttells you
File ... line 4, in <module>where it started: the call
File ... line 2, in greetwhere it actually failed
return "Hi " + naemthe exact line
NameError: name 'naem' is not definedthe type and reason

16. The line number points at the spot

Concept

Each frame gives a file and line number, and shows the offending line with a caret ^ under the problem.

Jump to that line first - the bug is there or very close to it.

17. The Usual Suspects

Section

Part 3

18. NameError

Concept

NameError: name 'x' is not defined - you used a name Python does not know: a typo, forgotten quotes, or a variable used before it was created.

19. NameError in action

Worked example

print(x)

x was never assigned

Why: No variable x exists, so Python cannot look it up.

codeerror
print(x)NameError: name 'x' is not defined

Fix

Why: Define x first (x = 5), add quotes if you meant text, or fix the spelling.

20. Draw the shape of it: NameError in action

Blank canvas

Draw it

Draw what NameError in action just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.

21. TypeError

Concept

TypeError - an operation got the wrong type, like adding a string and a number.

22. Where does each piece belong: Session 12 - Errors & Debugging

Sorting

Sort into buckets

These are the pieces of Session 12 - Errors & Debugging, out of order. Put each one back under the part of the lesson it belongs to.

Errors Are Normal
Everyone's code errors; An error stops and explains; The error is trying to help
Reading a Traceback
Read from the bottom up; Anatomy of a traceback; The line number points at the spot
The Usual Suspects
NameError; NameError in action; TypeError
s1
Errors Are Normal is where Session 12 - Errors & Debugging puts Everyone's code errors, An error stops and explains, The error is trying to help. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s2
Reading a Traceback is where Session 12 - Errors & Debugging puts Read from the bottom up, Anatomy of a traceback, The line number points at the spot. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s3
The Usual Suspects is where Session 12 - Errors & Debugging puts NameError, NameError in action, TypeError. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.

23. TypeError in action

Worked example

print("a" + 5)

str + int is not allowed

Why: One side is text, the other a number.

codeerror
"a" + 5TypeError: can only concatenate str (not "int") to str

Fix

Why: Convert one side: "a" + str(5), or use a comma / f-string.

24. ValueError

Concept

ValueError - the type was right but the value was not usable, like converting non-numeric text with int().

25. ValueError in action

Worked example

print(int("abc"))

"abc" is not a number

Why: int() got a string (right type) but no digits to read (wrong value).

codeerror
int("abc")ValueError: invalid literal for int() with base 10: 'abc'

Fix

Why: Only convert text that is actually numeric - or guard it with try/except (coming up).

26. Why is this step legal: IndexError: past the end of a list

Explain it to yourself

Discussion prompt

In IndexError and KeyError this move is made:

IndexError: past the end of a list

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

The list has indexes 0 and 1; 5 is out of range.

27. IndexError and KeyError

Worked example

print([1, 2][5])
print({"a": 1}["b"])

IndexError: past the end of a list

Why: The list has indexes 0 and 1; 5 is out of range.

KeyError: a missing dict key

Why: Verified by execution: the dict has no key "b".

codeerror
[1, 2][5]IndexError: list index out of range
{"a": 1}["b"]KeyError: 'b'

28. What each one costs: IndexError and KeyError

Trade off

Comparison matrix

From IndexError and KeyError: every row here is a choice with a cost. Fill the error column, then say which row you would actually pick and what you give up for it.

codeerror
[1, 2][5]IndexError: list index out of range
{"a": 1}["b"]KeyError: 'b'

29. ZeroDivisionError

Worked example

print(10 / 0)

Dividing by zero is undefined

Why: Python refuses and reports the reason.

codeerror
10 / 0ZeroDivisionError: division by zero

Fix

Why: Check the divisor first: if divisor != 0, or guard with try/except.

30. SyntaxError and IndentationError are different

Concept

SyntaxError and IndentationError happen before the program runs - the code is not valid Python, so nothing executes.

The others above happen while running. A syntax error means 'I cannot even read this line'; a runtime error means 'I ran, then hit a problem'.

31. Handling: try / except

Section

Part 4

32. try runs risky code; except catches

Concept

Put risky code in a try: block. If it raises an error, Python jumps to the except: block instead of crashing.

This lets a bad input recover gracefully rather than stopping the whole program.

33. Restore the missing line: Guarding a conversion

Fill the middle

Fill in the blanks

From Guarding a conversion — one line has had its right-hand side removed. Put it back.

try:
age = int(input("Age? "))
print("Next year:", age + 1)
except ValueError:
print("Please type a whole number.")

Why: age is what everything below it consumes, so the wrong expression here fails later and somewhere else. "abc" cannot convert, so a ValueError is raised.

34. Guarding a conversion

Worked example

The user types abc:

try:
    age = int(input("Age? "))
    print("Next year:", age + 1)
except ValueError:
    print("Please type a whole number.")

The int() fails inside try

Why: "abc" cannot convert, so a ValueError is raised.

except handles it instead of crashing

Why: Verified by execution: prints Please type a whole number. A valid number would run the try block normally.

user typespathprints
abcexceptPlease type a whole number.
20tryNext year: 21

35. Inspect it line by line: Guarding a conversion

Error analysis

Annotate

Walk the callouts on Guarding a conversion. Each one is a place this is easy to get subtly wrong.

  • "abc" cannot convert, so a ValueError is raised.
  • Verified by execution: prints Please type a whole number. A valid number would run the try block normally.

36. Catch a specific error type

Concept

Name the error after except: except ValueError:. This catches only that kind, and lets unrelated bugs still surface.

Catch the specific error you expect, not everything - that way real, unexpected bugs are not hidden.

37. Why is this step legal: Read the output

Explain it to yourself

Discussion prompt

In Only the error you expect this move is made:

Read the output

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

Verified by execution: prints cannot divide by zero. A different error would not be caught here.

38. Only the error you expect

Worked example

try:
    print(10 / 0)
except ZeroDivisionError:
    print("cannot divide by zero")

except ZeroDivisionError matches

Why: The division raises exactly that error, so this block runs.

Read the output

Why: Verified by execution: prints cannot divide by zero. A different error would not be caught here.

error raisedcaught?
ZeroDivisionErroryes
(a different error)no - surfaces normally

39. try/except is a safety net

Intuition

Picture a tightrope walker with a net. The try is the walk; the except is the net that catches a specific fall.

Use it where a fall is expected and recoverable - like user input - not to paper over bugs you have not understood.

40. Capture the message with as e

Concept

except ValueError as e: gives you the error object e, whose text you can print or log for more detail.

41. What rests on this: Capture the message with as e

Socratic

Discussion prompt

except ValueError as e: gives you the error object e, whose text you can print or log for more detail.

Suppose that were not true. What is the first thing in Session 12 - Errors & Debugging that would stop working?

Hint: Follow it one step downstream. The answer is whatever was quietly relying on it.

42. Why is this step legal: Read the output

Explain it to yourself

Discussion prompt

In Reading the message this move is made:

Read the output

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

Verified by execution: caught: invalid literal for int() with base 10: 'abc'.

43. Reading the message

Worked example

try:
    int("abc")
except ValueError as e:
    print("caught:", e)

e holds the error's message

Why: You can show it to help the user or yourself.

Read the output

Why: Verified by execution: caught: invalid literal for int() with base 10: 'abc'.

expressionprints
print("caught:", e)caught: invalid literal ... 'abc'

44. Guarding Input

Section

Part 5

45. Validate in a loop

Concept

Combine try/except with a loop: keep asking until the input converts cleanly, then break out.

This is the robust way to demand a number without crashing on a typo.

46. Why is this step legal: A good value breaks out

Explain it to yourself

Discussion prompt

In Keep asking until valid this move is made:

A good value breaks out

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

Verified by execution: prints not a number, try again, then got 12.

47. Keep asking until valid

Worked example

The user types abc, then 12:

while True:
    try:
        n = int(input("A number: "))
        break
    except ValueError:
        print("not a number, try again")
print("got", n)

A bad value is caught and the loop repeats

Why: abc raises ValueError, so except runs and the loop asks again.

A good value breaks out

Why: Verified by execution: prints not a number, try again, then got 12.

user typesresult
abcnot a number, try again
12got 12

48. Guard division by zero

Concept

You can check first (if b != 0:) or catch the error (except ZeroDivisionError). Either prevents a crash.

49. Why is this step legal: Check the divisor before dividing

Explain it to yourself

Discussion prompt

In A safe divide this move is made:

Check the divisor before dividing

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

If b is 0, return a message instead of dividing.

50. A safe divide

Worked example

def safe_divide(a, b):
    if b == 0:
        return "undefined"
    return a / b

print(safe_divide(10, 2))
print(safe_divide(10, 0))

Check the divisor before dividing

Why: If b is 0, return a message instead of dividing.

Read the output

Why: Verified by execution: 5.0, then undefined.

callreturns
safe_divide(10, 2)5.0
safe_divide(10, 0)undefined

51. Handling Carefully

Section

Part 6

52. Something is wrong here: a bare except hides bugs

Anomaly

Predict first

A student writes this, and it looks reasonable:

Catching everything with a bare except.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: inpt is a typo for input - a NameError.

Catch only the error you expect.

Why: inpt is a typo for input - a NameError. But the bare except catches it too and blames 'bad input', hiding the actual mistake.

53. Trap: a bare except hides bugs

Trap

The trap

Catching everything with a bare except.

try:
    n = int(inpt("Age? "))
except:
    print("bad input")

It swallows the real bug

Why: inpt is a typo for input - a NameError. But the bare except catches it too and blames 'bad input', hiding the actual mistake.

real problemwhat you see
NameError (typo inpt)bad input

The fix

Catch only the error you expect.

try:
    n = int(input("Age? "))
except ValueError:
    print("please type a number")

A ValueError is handled; other bugs surface

Why: Now a typo like inpt would raise a NameError you can see and fix, instead of being masked. Catch narrowly.

errorbehavior
ValueErrorhandled kindly
NameError (a real bug)surfaces so you fix it

54. Fill in: behavior for Trap: a bare except hides bugs

Comparison

Comparison matrix

From Trap: a bare except hides bugs: refill the behavior column from what you know. The rest of the table is as it appeared.

errorbehavior
ValueErrorhandled kindly
NameError (a real bug)surfaces so you fix it

55. Catch what you can handle

Concept

Only wrap code in try/except when you have a sensible recovery. If you cannot recover, let it crash - the traceback is more useful than a swallowed error.

56. Something is wrong here: catching the wrong type

Anomaly

Predict first

A student writes this, and it looks reasonable:

Expecting except TypeError to catch a bad conversion.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: The except only catches TypeError, so the ValueError slips past and the program still crashes.

Match the except to the error actually raised.

Why: The except only catches TypeError, so the ValueError slips past and the program still crashes.

57. Trap: catching the wrong type

Trap

The trap

Expecting except TypeError to catch a bad conversion.

try:
    n = int("abc")
except TypeError:
    print("handled")

int("abc") raises ValueError, not TypeError

Why: The except only catches TypeError, so the ValueError slips past and the program still crashes.

raisedexcept catchesresult
ValueErrorTypeErrorstill crashes

The fix

Match the except to the error actually raised.

try:
    n = int("abc")
except ValueError:
    print("handled")

except ValueError matches

Why: Now the right error is caught. Real output: handled. Read the traceback to learn which type to catch.

raisedexcept catchesresult
ValueErrorValueErrorhandled

58. Which of these survive contact with Session 12 - Errors & Debugging?

Two truths and a lie

Sort into buckets

Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.

Holds up
Errors are not a sign you are bad at this - they are a normal, constant part of programming for everyone.; When Python hits something it cannot do, it stops and prints a traceback - a report of what went wrong and where.; Treat the red text as a helpful note, not a scolding. It literally tells you the file, the line, and the reason.
Breaks
Catching everything with a bare except.; Expecting except TypeError to catch a bad conversion.
sound
These are stated as this lesson states them — each one survives the edge cases Session 12 - Errors & Debugging puts it through.
flawed
Each of these is lifted from a trap in this deck: reasonable-sounding, and wrong in a way that only shows up once you rely on it.

59. Debugging with print

Section

Part 7

60. Print to see what is really happening

Concept

When a result is wrong (but not an error), add print() to show a variable's value at key points. Seeing the actual value usually reveals the bug.

61. Finding a logic bug

Worked example

total = 0
for n in [1, 2, 3]:
    total = n
    print("debug total:", total)
print("final:", total)

The debug prints expose the mistake

Why: total = n (not total += n) overwrites instead of accumulating - the prints show total is 1, 2, 3, not 1, 3, 6.

Read the trace

Why: Verified by execution: final is 3, revealing the bug. The fix is total += n.

ndebug total
11
22
33

62. Watch it run: Finding a logic bug

Pattern

Step through it

Step through Finding a logic bug one row at a time. What is driving the change, and what would the row after the last one be?

  1. Step 1: n is 1
  2. Step 2: n is 2
  3. Step 3: n is 3

63. Reproduce, then narrow

Concept

Find the smallest input that shows the bug (reproduce it reliably), then add prints or comment out lines to narrow where it goes wrong.

Change one thing at a time, and re-run. Guessing randomly wastes time; narrowing finds it.

64. Debugging is detective work

Intuition

Form a guess ('total is not adding up'), gather evidence (print it), and confirm or rule out. It is small, patient science.

The traceback and a few well-placed prints are almost always enough to catch the culprit.

65. More Handling in Practice

Section

Part 8

66. Catch several types at once

Concept

List related errors in parentheses: except (ValueError, ZeroDivisionError): handles either with one block.

67. One block, two errors

Worked example

for val in ["abc", "0"]:
    try:
        print(100 / int(val))
    except (ValueError, ZeroDivisionError):
        print("skipped bad value")

Both bad cases are caught

Why: "abc" raises ValueError; "0" causes ZeroDivisionError. The tuple covers both.

Read the output

Why: Verified by execution: skipped bad value, twice.

valerrorprints
abcValueErrorskipped bad value
0ZeroDivisionErrorskipped bad value

68. Draw the shape of it: One block, two errors

Blank canvas

Draw it

Draw what One block, two errors just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.

69. finally runs no matter what

Concept

A finally: block runs whether or not an error happened - use it for cleanup that must always occur.

70. Teach it back: finally runs no matter what

Explain it

Discussion prompt

Explain finally runs no matter what to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

A finally: block runs whether or not an error happened - use it for cleanup that must always occur.

71. Why is this step legal: finally always executes

Explain it to yourself

Discussion prompt

In Cleanup with finally this move is made:

finally always executes

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

Even if the try had raised, the finally block would still run.

72. Cleanup with finally

Worked example

try:
    print("working")
finally:
    print("cleanup runs")

finally always executes

Why: Even if the try had raised, the finally block would still run.

Read the output

Why: Verified by execution: working, then cleanup runs.

blockruns?
tryyes
finallyalways

73. Inspect it line by line: Cleanup with finally

Error analysis

Annotate

Walk the callouts on Cleanup with finally. Each one is a place this is easy to get subtly wrong.

  • Even if the try had raised, the finally block would still run.
  • Verified by execution: working, then cleanup runs.

74. Return a default on failure

Concept

Wrap a risky conversion in a helper that returns a fallback if it fails - turning a crash into a safe default.

75. By analogy: Return a default on failure

Analogy

Discussion prompt

Explain Return a default on failure by analogy to something with no Python Fundamentals in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

Wrap a risky conversion in a helper that returns a fallback if it fails - turning a crash into a safe default.

76. A forgiving to_int

Worked example

def to_int(s, default=0):
    try:
        return int(s)
    except ValueError:
        return default

print(to_int("7"))
print(to_int("x"))

Success returns the number; failure returns the default

Why: "7" converts to 7; "x" fails, so it returns 0.

Read the output

Why: Verified by execution: 7 then 0.

callreturns
to_int("7")7
to_int("x")0

77. What each one costs: A forgiving to_int

Trade off

Comparison matrix

From A forgiving to_int: every row here is a choice with a cost. Fill the returns column, then say which row you would actually pick and what you give up for it.

callreturns
to_int("7")7
to_int("x")0

78. Fail gracefully

Intuition

A robust program bends instead of breaking: skip a bad row, ask again, or use a sensible default - rather than crashing on the first surprise.

But only where recovery makes sense. Silent defaults everywhere can hide real problems, so use them thoughtfully.

79. Break it if you can: Fail gracefully

Counterexample

Discussion prompt

A robust program bends instead of breaking: skip a bad row, ask again, or use a sensible default - rather than crashing on the first surprise.

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

80. Predict the next row: Average, skipping bad entries

Pattern

Predict first

The table runs: 10 | yes | 10 · oops | no | 10

In Average, skipping bad entries, given the rows so far: what is the next one — the row where r is 20?

Correct: 20 | yes | 30

rcounted?total
10yes10
oopsno10
20yes30

Why: The relationship between the columns, not the individual numbers, is what generates the next row. "oops" raises ValueError, caught and ignored; only 10 and 20 count.

81. Average, skipping bad entries

Worked example

raw = ["10", "oops", "20"]
total = 0
count = 0
for r in raw:
    try:
        total += int(r)
        count += 1
    except ValueError:
        pass
print(total / count)

Bad entries are skipped with pass

Why: "oops" raises ValueError, caught and ignored; only 10 and 20 count.

Read the output

Why: Verified by execution: (10 + 20) / 2 = 15.0. pass means 'do nothing and move on'.

rcounted?total
10yes10
oopsno10
20yes30

82. Fill in: total for Average, skipping bad entries

Comparison

Comparison matrix

From Average, skipping bad entries: refill the total column from what you know. The rest of the table is as it appeared.

rcounted?total
10yes10
oopsno10
20yes30

83. Patterns & Checks

Section

Part 9

84. Reading an error

Pattern

1. Read the LAST line: the type and message

Why: NameError, TypeError, ValueError, etc. - it names the problem.

2. Find the file and line number

Why: The bottom frame shows where it actually failed; jump there.

3. Match the message to the cause

Why: 'not defined' -> typo/quotes; 'concatenate str' -> mixed types; 'invalid literal' -> bad conversion.

4. Fix one thing, re-run

Why: Change the smallest thing that addresses the message, then run again.

85. Why is this step legal: Use it for expected, recoverable failures

Explain it to yourself

Discussion prompt

In When to use try/except this move is made:

Use it for expected, recoverable failures

Why is that legal? Name the rule or definition it rests on before you read on.

Hint: If you can only say "because that is what you do", the rule is the thing to go and find.

Answer:

Bad user input, a missing optional value - things you can respond to.

86. When to use try/except

Pattern

Use it for expected, recoverable failures

Why: Bad user input, a missing optional value - things you can respond to.

Catch the specific type, never bare except

Why: except ValueError, not except: - so real bugs still surface.

If you cannot recover, let it crash

Why: The traceback is more useful than a hidden error.

87. Where this shows up: Session 12 - Errors & Debugging

Real world

Discussion prompt

Outside this lesson: where does Session 12 - Errors & Debugging actually turn up? Name one concrete situation — a job, a piece of software someone ships, a decision somebody has to make — and say which part of When to use try/except is doing the work in it.

Hint: Vague is the failure mode here. "Engineering" is not a situation; "deciding whether this build is fast enough to ship" is.

Answer:

Session 12 of the Python Fundamentals series, in depth. Stop fearing the red text: read a traceback from the bottom up; recognize the common errors (NameError, TypeError, ValueError, IndexError, KeyError, ZeroDivisionError, SyntaxError, IndentationError) and their exact messages; guard risky code with try/except, catch specific error types, capture the message with 'as e', validate input in a loop; and debug by printing values, reproducing, and narrowing.

88. Check: name the error

Check

What error is this?

print(int("12x"))
codeerror type
int("12x")?

Check your understanding

Which error does this raise?

  • A. ValueError (correct)
  • B. TypeError
  • C. NameError
  • D. SyntaxError

Answer: A

Why: int() received a string of the right type but with non-numeric characters, so it raises a ValueError (invalid literal). Verified by execution.

Why B tempts people
TypeError is for wrong types; here the type (str) is fine, but the value is not numeric.
Why C tempts people
NameError is for undefined names; "12x" is a literal, not a name.
Why D tempts people
The line is valid syntax and does run - it fails at runtime, not before.

89. Rule out three: Check: where to look first

Elimination

Eliminate the wrong options

Which line do you read first to know what went wrong?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. The last line (the error type and message)
  • B. The first line (Traceback most recent call last)
  • C. The File line 4 frame
  • D. It does not matter

Survives elimination: A

Why: The last line names the error type and reason - the fastest way to understand the failure. Then work upward to the failing line. Verified by how Python formats tracebacks.

90. Check: where to look first

Check

A traceback prints several lines.

# Traceback (most recent call last):
#   File ..., line 4, in <module>
#   File ..., line 2, in greet
# NameError: name 'naem' is not defined
read orderline
first?

Check your understanding

Which line do you read first to know what went wrong?

  • A. The last line (the error type and message) (correct)
  • B. The first line (Traceback most recent call last)
  • C. The File line 4 frame
  • D. It does not matter

Answer: A

Why: The last line names the error type and reason - the fastest way to understand the failure. Then work upward to the failing line. Verified by how Python formats tracebacks.

Why B tempts people
The first line is just a header; it does not tell you the specific error.
Why C tempts people
That frame shows where execution started, not where it failed - the failing frame is lower.
Why D tempts people
Order matters: reading the bottom line first is the reliable way to diagnose.

91. Check: which except?

Check

The user types letters.

try:
    n = int(input())
except ____:
    print("try again")
int on letters raisesso catch
ValueError?

Check your understanding

What should fill the blank?

  • A. ValueError (correct)
  • B. TypeError
  • C. NameError
  • D. (leave it bare)

Answer: A

Why: int() on non-numeric text raises ValueError, so that is the type to catch. Verified by execution.

Why B tempts people
int() on a string does not raise TypeError - the type is fine, the value is not.
Why C tempts people
There is no undefined name here, so NameError would never match.
Why D tempts people
A bare except would also hide unrelated bugs; catch the specific ValueError.

92. Check: try/except flow

Check

Trace the path.

try:
    x = int("5")
    print("a")
except ValueError:
    print("b")
print("c")
int("5")path
works?

Check your understanding

What does this print?

  • A. a then c (correct)
  • B. b then c
  • C. a then b then c
  • D. c only

Answer: A

Why: int("5") succeeds, so the try block prints a and the except is skipped; then c prints after. Verified by execution.

Why B tempts people
The except only runs if the try raises an error. int("5") succeeds, so b is skipped.
Why C tempts people
The except does not run when the try succeeds, so b never prints.
Why D tempts people
The try block runs fully (printing a) since there was no error.

93. Check: the bare-except danger

Check

There is a typo: prnt instead of print.

try:
    prnt("hi")
except:
    print("something went wrong")
real bughidden?
NameError (prnt)?

Check your understanding

Why is this bare except a problem?

  • A. It hides the NameError typo behind a vague message (correct)
  • B. It is a SyntaxError
  • C. It prints hi
  • D. except cannot follow try

Answer: A

Why: prnt is undefined (NameError), but the bare except catches everything and prints a vague message, hiding the real typo. Catching NameError-level bugs like this makes debugging harder. Verified by reasoning about bare except.

Why B tempts people
It is valid syntax; the error is a runtime NameError from the typo, which the bare except swallows.
Why C tempts people
prnt does not exist, so hi is never printed - the except runs instead.
Why D tempts people
except can follow try - the issue is that a BARE except catches too much.

94. Connect it up: Session 12 - Errors & Debugging

Connect it up

Draw it

One page, no notation unless you need it: draw how these connect — Errors Are Normal · Reading a Traceback · The Usual Suspects · Handling: try / except · Guarding Input · Handling Carefully. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.

95. What you can do now

Recap

Read tracebacks bottom-up, recognize the common errors, and guard expected failures with try / except on a specific type.

Message hintLikely cause
name ... is not definedtypo, missing quotes, used-before-set
can only concatenate strmixed str and number
invalid literal for int()converting non-numeric text
list index out of rangeindex past the end
KeyErrormissing dict key
division by zerodivided by 0

Debug by printing values, reproducing, and narrowing. Next session we start the capstone: planning and building a multi-room adventure game.

Sources

  1. Python 3 Tutorial - Errors and Exceptions
  2. Python 3 Library Reference - Built-in Exceptions
  3. All snippets, messages, and tracebacks executed and copied from CPython 3.12. — Author verification run, 2026-07-15 (Python Fundamentals series, Session 12).

Want this taught 1-on-1? Alexander tutors Python Fundamentals — $55/session, free consultation.

Book on Wyzant · Text (657) 465-8108