When I started with Python, the worst part wasn't writing code — it was the moment the code refused to run and dumped half a screen of red text at me. My reaction, for months, was to skim the top line, panic, and start changing random things.
The turn-around was learning one habit: tracebacks are written to be read from the bottom up. The last line tells you what went wrong; the lines above tell you where. Once that clicked, errors stopped being insults and started being directions.
Take this genuinely broken little program:
def average(numbers):
return sum(numbers) / len(numbers)
scores = ["80", "95", "67"]
print(average(scores))
Run it and Python prints:
Traceback (most recent call last):
File "grades.py", line 6, in <module>
print(average(scores))
File "grades.py", line 2, in average
return sum(numbers) / len(numbers)
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Read it the way it wants to be read:
TypeError. Python tried to add an int to a str. sum() starts from 0, and the first thing it meets is the string "80". The scores are strings, not numbers.The fix follows directly: convert the values, int(s) for s in scores, or better, don't put strings in a list you're going to do math on.
SyntaxError: the program never ran at allThis one is special: it's reported before any of your code executes, and the message can feel cryptic:
names = ["Ada", "Linus"
print(names)
File "demo.py", line 1
names = ["Ada", "Linus"
^
SyntaxError: '[' was never closed
Newer Python versions are good about pointing at the actual problem — an unclosed bracket here. Two things worth knowing:
^) marks where the parser gave up, which is often one or two lines after your real mistake. A forgotten comma on line 10 is usually reported as a complaint about line 11.invalid syntax on a line that looks perfectly fine, re-read the line above it.KeyError: the key that isn't thereuser = {"name": "Ada", "language": "en"}
print(user["age"])
KeyError: 'age'
The good news: a KeyError is never mysterious. The message is the missing key. You have three standard moves, in order of preference:
user.get("age", "unknown") # a default value when it's absent
"age" in user # an explicit check
user["age"] # let it fail — when absence is a real bug
That last line is not a joke. Sometimes a missing key should crash your program, loudly, because it means your data is wrong in a way you want to hear about. Errors are information; silencing them isn't the same as handling them.
So: last line first — what broke? Then the first file and line number in the traceback that points at your code (rather than deep inside a library) — where did it break? Fix that, run again, and repeat. It sounds obvious written down, but under time pressure everyone forgets it.
And when an error type is unfamiliar, the last line is exactly what you paste into a search box: TypeError: unsupported operand type(s) for +: 'int' and 'str' will get you a Stack Overflow thread with your exact problem on the first try. The traceback isn't the punishment — it's the answer key.