Read a Python traceback from the bottom up to find what went wrong, where, and how the program got there.
About 30 minBeginner4 exercisesFree
You will be able to
Name the parts of a traceback: header, frames, code lines, markers and the final error line
Read a traceback bottom-up to find the exception type and message first
Find the frame that points at your own code and the value that caused the problem
Follow a chain of function calls through the frames to see how the program reached the error
You run an order script against this morning's export and, instead of a total, you get eleven lines of red text. It is tempting to scroll past it and start changing code at random. Don't. That red text is a traceback, and it is the most precise bug report you will ever receive: it names the kind of problem, the value involved, the exact line, and every function call that led there.
When Python meets an operation it cannot carry out — looking up a key that does not exist, dividing by zero, adding text to a number — it creates an exception: an object describing the problem. If nothing in the program handles that exception, Python stops the program and prints the traceback. In this track you will learn to handle exceptions deliberately. First you need to read them.
An order total that crashes on an unknown product code
prices ={"SKU-101": 12.5,"SKU-205": 4.75}defline_total(sku, qty):
unit = prices[sku]return unit * qty
deforder_total(lines):
total =0for sku, qty in lines:
total += line_total(sku, qty)return total
print(order_total([("SKU-101",2),("SKU-309",1)]))
Try it: Add "SKU-309": 7.0 to the prices dictionary and run it again. The traceback disappears and the total prints.
The traceback this prints looks like this:
Traceback (most recent call last):
File "main.py", line 13, in <module>
print(order_total([("SKU-101", 2), ("SKU-309", 1)]))
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "main.py", line 10, in order_total
total += line_total(sku, qty)
~~~~~~~~~~^^^^^^^^^^
File "main.py", line 4, in line_total
unit = prices[sku]
~~~~~~^^^^^
KeyError: 'SKU-309'
Its parts, from top to bottom:
Part
Example
Meaning
Header
Traceback (most recent call last):
The frames below are listed oldest first, newest last.
Frame
File "main.py", line 10, in order_total
One function call that was still running: the file, the line number and the function's name. <module> means the top level of the file, outside any function.
Code line
total += line_total(sku, qty)
The source line Python was running in that frame.
Markers
~~~~~~^^^^^
Python 3.11+ underlines the exact expression; ^ marks the part that failed.
Error line
KeyError: 'SKU-309'
The exception type, a colon, then the message.
Read it from the bottom up
The header says "most recent call last", so the most useful information is at the bottom:
Last line first.KeyError: 'SKU-309' — a dictionary lookup failed, and the missing key was 'SKU-309'. Often this alone tells you the bug.
The last frame.line 4, in line_total — the line that actually failed is unit = prices[sku].
Work upwards to see how you got there: line_total was called by order_total on line 10, which was called from the top of the file on line 13.
The bug is rarely "in" the top frame. Line 13 is only where the chain of calls started. The fix here belongs either in the data (add the missing price) or in line_total (decide what an unknown product should do — a question this track answers in later lessons).
A message that names the wrong type
defformat_line(name, qty):
return name +" x"+ qty
defprint_receipt(items):
for name, qty in items:
print(format_line(name, qty))
print_receipt([("Kiwi",3),("Dates",1)])
Try it: Read the last line of the traceback, then change qty to str(qty) inside format_line and run it again.
The last line here is TypeError: can only concatenate str (not "int") to str. Read the message literally: something tried to join a string with an integer using +. The last frame points at return name + " x" + qty in format_line, and the ^ marker sits under the second +. The value of qty came from print_receipt, one frame up, which got it from the list on the last line of the program.
Notice what did not happen: Kiwi was never printed. The exception stopped the program in the middle of the first loop iteration, before print() received anything.
Guided practice · ●difficulty 1 of 5 · about 4 min
Name the culprit
An attendance script crashed. Here is the program, with line numbers:
Traceback (most recent call last):
File "main.py", line 10, in <module>
report(["Lina", "Omar", "Yusuf"])
~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "main.py", line 8, in report
print(name, rate(attendance[name]))
~~~~~~~~~~^^^^^^
KeyError: 'Yusuf'
Read it and record what you found in four variables:
error_type — the exception type, as a string (for example "ValueError")
error_line — the line number (an int) where the error actually happened
error_function — the name of the function that line belongs to, as a string
bad_value — the value that caused the problem, as a string without extra quotes
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Traceback (most recent call last):
File "main.py", line 10, in <module>
receipt([("Kiwi", 3, 4.5)])
~~~~~~~^^^^^^^^^^^^^^^^^^^^
File "main.py", line 8, in receipt
lines.append(format_line(name, qty, price))
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
File "main.py", line 3, in format_line
return name + " x" + qty + " = " + f"{total:.2f}" + " SAR"
~~~~~~~~~~~~^~~~~
TypeError: can only concatenate str (not "int") to str
Read the traceback, find the line that failed and fix it. When it works:
format_line("Kiwi", 3, 4.5) returns "Kiwi x3 = 13.50 SAR" (total with exactly two decimals)
receipt(items) returns a list with one formatted line per item, and [] for an empty order.
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Challenge · ●●●difficulty 3 of 5 · about 12 min
Pull the facts out of a traceback
A support team pastes tracebacks from customers' crash reports into a ticket system. Write a function last_frame(tb) that takes the traceback text and returns a dictionary with the four facts you read first:
"error" — the exception type from the final line
"message" — everything after the first ": " on the final line (an empty string if there is no message)
"line" — the line number of the last frame, as an int
"function" — the function name of the last frame
Frame lines look like File "main.py", line 4, in line_total. Example: for the order traceback from this lesson, last_frame(tb) returns
Ignore blank lines, including blank lines at the end of the text. Messages can themselves contain ": ", so split only once.
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Edge cases · ●●difficulty 2 of 5 · about 6 min
The latest sensor reading
A greenhouse dashboard shows the latest temperature from each sensor. It crashes for every sensor:
Traceback (most recent call last):
File "main.py", line 12, in <module>
print(latest_summary("Greenhouse A", [21.5, 22.0, 22.4]))
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "main.py", line 6, in latest_summary
value = latest_reading(readings)
File "main.py", line 2, in latest_reading
return readings[len(readings)]
~~~~~~~~^^^^^^^^^^^^^^^
IndexError: list index out of range
Fix latest_reading(readings) so it returns the last reading in the list. A sensor that has not reported yet has an empty list: then latest_reading must return None, so that latest_summary can show "Greenhouse A: no data".
Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.
Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type
Output
Run your code to see its output, or Check to test it against the requirements.
The solution becomes available after you pass, or after all three hints and two checks.
Summary
An unhandled exception stops the program and prints a traceback: frames oldest first, the error last.
Read bottom-up: the final line gives the exception type and message; the last frame gives the failing line.
Each frame names a file, a line number and a function; <module> means the top level of the file.
Walk up the frames to see how the bad value reached the failing line; stop at the first frame in your own code.