Python Module 1 – Getting started: install, run and read Python
Read error messages and tracebacks calmly
Read a Python traceback from the bottom up, recognise the errors beginners meet most often, and use the clearer messages of Python 3.14 to fix the failing line.
What you will learn
- Read a traceback from the bottom up to find the failing line
- Recognise the most common beginner exceptions and their usual causes
- Use help(), the documentation and minimal examples to get unstuck
Before you start
On this page
When a program fails, Python stops and prints a traceback. The first few look alarming, but a traceback is a precise report with three parts: what went wrong, the line where it happened, and the chain of calls that led there. Reading one in that order, from the bottom up, is the quickest way to find most bugs.
Read it from the bottom up
This program adds up two bills. The first one works; the second has a typo in its order:
prices = {"tea": 30, "toast": 45, "coffee": 60}
def line_total(item, quantity):
return prices[item] * quantity
def bill(order):
total = 0
for item, quantity in order:
total += line_total(item, quantity)
return total
print("First bill:", bill([("tea", 2), ("toast", 1)]))
print("Second bill:", bill([("tea", 1), ("cofee", 2)])) Output (exit status 1)
First bill: 105
Printed as an error (standard error)
Traceback (most recent call last):
File "bill.py", line 16, in <module>
print("Second bill:", bill([("tea", 1), ("cofee", 2)]))
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "bill.py", line 11, in bill
total += line_total(item, quantity)
~~~~~~~~~~^^^^^^^^^^^^^^^^
File "bill.py", line 5, in line_total
return prices[item] * quantity
~~~~~~^^^^^^
KeyError: 'cofee'
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 bill.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
Start at the last line and work upwards:
- The last line names the exception and gives its message.
KeyError: 'cofee'says that a dictionary was asked for a key it does not have, and the message is that key. - The frame just above it shows where it happened:
File "bill.py", line 5, in line_total, then the line itself. The~and^marks under it pick out the part of the line that failed, the lookupprices[item]. - Each frame higher up is a call that led there.
bill()calledline_total()on line 11, and the file’s top level (<module>) calledbill()on line 16. “Most recent call last” means the frames run from the first call down to the line that failed.
The line that failed is not always the line to fix. Nothing is wrong with line_total(): it was given a bad value.
Keep reading upwards until you reach the line where the bad value came from, here the order on line 16. Notice too
that the first bill was printed: everything before the failing line ran normally.
When the failing frames are not your code
If you pass something wrong to a function of the standard library or of a package, the last frames are inside that function’s own files:
import json
settings_text = "{'theme': 'dark'}"
settings = json.loads(settings_text)
print("Theme:", settings["theme"]) Output (exit status 1)
Printed as an error (standard error)
Traceback (most recent call last):
File "bad_json.py", line 4, in <module>
settings = json.loads(settings_text)
File "…/lib/python3.14/json/__init__.py", line 352, in loads
return _default_decoder.decode(s)
~~~~~~~~~~~~~~~~~~~~~~~^^^
File "…/lib/python3.14/json/decoder.py", line 345, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
File "…/lib/python3.14/json/decoder.py", line 361, in raw_decode
obj, end = self.scan_once(s, idx)
~~~~~~~~~~~~~~^^^^^^^^
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 bad_json.py
The frames under …/lib/python3.14/json/ belong to Python’s json module (the … stands for the folder Python is
installed in, which differs from one computer to the next). Do not go looking for a bug there. Find the last frame
that is in your own file, line 4, where json.loads() was called, and check what you gave it. The message says the
rest: JSON needs double quotes around names, so the text should have been '{"theme": "dark"}'.
A SyntaxError means nothing ran
Python reads a whole file before running any of it. When the grammar is wrong, it reports a SyntaxError and runs
nothing at all, not even the lines above the mistake:
print("This line never runs")
def greeting(name):
retrun "Hello, " + name
print(greeting("Asha")) Output (exit status 1)
Printed as an error (standard error)
File "typo_keyword.py", line 5
retrun "Hello, " + name
^^^^^^
SyntaxError: invalid syntax. Did you mean 'return'?
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 typo_keyword.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
There is no “Traceback (most recent call last)” line this time, because no call happened: the file never started. The
first line, a print(), printed nothing for the same reason.
Version note
New in Python 3.14: when a word looks like a misspelt keyword, the message suggests the keyword, as in
Did you mean 'return'? above. Python 3.13 and older say only invalid syntax.
Sometimes the line Python shows looks perfectly fine. The cause is then usually earlier, often a bracket or a quote that was opened and never closed. Python points at where it was opened:
marks = [72, 88, 95
print(sum(marks) / len(marks)) Output (exit status 1)
Printed as an error (standard error)
File "unclosed.py", line 1
marks = [72, 88, 95
^
SyntaxError: '[' was never closed
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 unclosed.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
The list on line 1 never gets its ]. Inside brackets Python keeps reading on the following lines, so it reaches the
end of the file still inside the list, and reports the line where the list began.
IndentationError, for lines indented in a way that does not match the blocks around them, is a kind of
SyntaxError too and is reported the same way, before anything runs.
The errors you will meet most
Each of these eight lines makes a different mistake. The program runs them one at a time and prints the last line of each traceback, so you can see the exact messages of this version of Python:
import traceback
# Eight one-line mistakes. exec() runs each line as a tiny program and the error is caught,
# so you see the last line of every traceback, exactly as Python prints it.
mistakes = [
"print(scroe)",
'"3" + 4',
'int("three")',
"[10, 20, 30][3]",
'{"tea": 30}["coffee"]',
'"text".uper()',
"1 / 0",
"import numpyy",
]
for code in mistakes:
try:
exec(code)
except Exception as error:
last_line = traceback.format_exception_only(error)[-1].strip()
print(f"{code:<24}{last_line}") Output
print(scroe) NameError: name 'scroe' is not defined
"3" + 4 TypeError: can only concatenate str (not "int") to str
int("three") ValueError: invalid literal for int() with base 10: 'three'
[10, 20, 30][3] IndexError: list index out of range
{"tea": 30}["coffee"] KeyError: 'coffee'
"text".uper() AttributeError: 'str' object has no attribute 'uper'. Did you mean: 'upper'?
1 / 0 ZeroDivisionError: division by zero
import numpyy ModuleNotFoundError: No module named 'numpyy'
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 error_gallery.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
When a name or an attribute is misspelt and something close to it exists, Python adds Did you mean …?, as for uper
above. What each error usually means, and where to look first:
| Error | It usually means | Look first at |
|---|---|---|
NameError |
A name is used that was never assigned, or is misspelt | The spelling, and whether the line that assigns it ran first |
TypeError |
A value of the wrong type for the operation, such as text plus a number | The types involved: convert with int(), float() or str() |
ValueError |
The right type with a value that does not fit, such as int("three") |
The data, often what the user typed or a file contained |
IndexError |
A position past the end of a list: the last one is len(items) - 1 |
A loop or a calculation that goes one step too far |
KeyError |
A dictionary has no such key; the message is the key | The key’s spelling, or use .get() when it may be missing |
AttributeError |
The object has no method or attribute of that name | The spelling, and the object’s type: print(type(value)) |
ZeroDivisionError |
Division by zero | Counts and lengths that can be 0, such as an empty list |
ModuleNotFoundError |
No module of that name for this Python | The spelling, and whether the package is installed in the environment you run |
IndentationError |
Indentation that does not match the blocks | A missing indented line after a colon, or tabs mixed with spaces |
RecursionError |
A function kept calling itself, by default about 1,000 levels deep | The case that should stop the recursion |
A common mistake: a file named after a module
Name your own file after a module you import, such as random.py, and Python imports your file instead of the
module. Python 3.13 and newer notice and say so:
import random
print("Your dice roll:", random.randint(1, 6)) Output (exit status 1)
Printed as an error (standard error)
Traceback (most recent call last):
File "random.py", line 1, in <module>
import random
File "random.py", line 3, in <module>
print("Your dice roll:", random.randint(1, 6))
^^^^^^^^^^^^^^
AttributeError: module 'random' has no attribute 'randint' (consider renaming 'random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 random.py
The script imports itself as random, so random.randint does not exist. The message even names the file to rename:
call it dice.py and import random finds the standard library’s module again. Python 3.12 and older report the same
mistake only as a “partially initialized module” and a possible circular import.
Clearer messages in Python 3.14
Python 3.14 improved several other messages too. Using a list as a dictionary key fails, as before, because keys must be hashable and a list, which can change, is not; but the message now says what you tried to do:
stock = {}
stock[["tea", "toast"]] = 2 Output (exit status 1)
Printed as an error (standard error)
Traceback (most recent call last):
File "unhashable.py", line 2, in <module>
stock[["tea", "toast"]] = 2
~~~~~^^^^^^^^^^^^^^^^^^
TypeError: cannot use 'list' as a dict key (unhashable type: 'list')
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 unhashable.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
Version note
Python 3.13 and older stop at TypeError: unhashable type: 'list'. Two older improvements show in every traceback
of this lesson: since Python 3.11 the ~ and ^ marks point at the exact part of a line that failed (PEP 657), and
since Python 3.13 tracebacks in a terminal are in colour, which the environment variables PYTHON_COLORS=0 and
NO_COLOR=1 turn off. The pages of What’s New list every improvement, version by version.
When you are stuck
-
Read the last line slowly and look the exception up on the Built-in Exceptions page of the Python documentation. In the shell,
help()shows the documentation of a function, a type or a module, andissubclass()tells you which broader kind of error an exception belongs to:Asking Python itself Python console · help_session.pycon >>> help(len) Help on built-in function len in module builtins: len(obj, /) Return the number of items in a container. >>> issubclass(KeyError, LookupError) True >>> issubclass(ModuleNotFoundError, ImportError) TrueThis session was replayed with Python 3.14.8 on macOS 26 arm64, and it printed exactly what is shown.
-
Print what you have. Just above the failing line, add
print(repr(value), type(value))for the values it uses. Most surprises are a value of a different type, or text with a space you cannot see. -
Make a minimal example. Copy the program and delete everything that is not needed to make the error happen, until only a few lines are left. You often find the bug on the way; if not, those few lines are what you show when you ask for help.
-
Search for the last line, leaving out the names and values that are particular to your program.
Security
Before you paste code or a traceback into a forum or an AI assistant, take out passwords, API keys, tokens and personal data. Tracebacks contain file paths, which often include your user name, and the code around each failing line.
Key takeaways
- Read a traceback from the bottom: the exception and its message, then the line that failed, then the calls above it.
- The bug is often higher up than the failing line: follow the bad value back to where it came from, and skip the frames inside libraries.
- A
SyntaxErrormeans nothing ran; when the line shown looks fine, look for an unclosed bracket or quote before it. - Python 3.14 suggests misspelt keywords and explains unhashable keys;
Did you mean …?hints for names and attributes are older. - Get unstuck with the documentation and
help(), aprint()of the values involved, and a minimal example, and never paste secrets into a question.
References
- The Python Tutorial: Errors and Exceptions (Python Software Foundation)
- Built-in Exceptions (Python Software Foundation)
- What's New In Python 3.14: improved error messages (Python Software Foundation)
- What's New In Python 3.13: improved error messages (Python Software Foundation)
- PEP 657: Include fine-grained error locations in tracebacks (Python Software Foundation)
- traceback, print or retrieve a stack traceback (Python Software Foundation)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress