Python is known as a beginner-friendly language, but it still has its share of hurdles that confuse even careful students. The good news is that most errors in Python assignments are not mysterious or complex. They are small, everyday mistakes, and you can avoid most of them once you know what to look for.
The same few mistakes come up again and again. Whether it is a missing colon, a misspelled variable, or a list index that goes one step too far, debugging can eat up hours if you do not know where to look. This guide works like a debugging checklist. First you will learn how to read Python's error message (the traceback). Then you will see the three types of errors in Python and the 10 errors students hit most, each with a real example and the fix. Last, you will learn how to handle errors with try and except, and when not to.
We ran every example on Python 3.13, so the error messages you see here are real. Older versions word a few messages a little differently, but the fixes are the same.
Still stuck on a Python homework problem? You can always get Python assignment help from our experts online.
The 10 errors at a glance:
| Error | What it usually means | Quick fix |
|---|---|---|
IndentationError | A line is not lined up with its block | Indent with 4 spaces, never mix tabs and spaces |
NameError | A variable is used before it exists, or is misspelled | Define it first, check the spelling and capitals |
TypeError | An operation got the wrong type, like text + number | Convert with int(), float(), or str() |
IndexError | A list position does not exist | Remember indexes start at 0, check len() |
KeyError | A dictionary key does not exist | Use .get() or check with in |
ZeroDivisionError | You divided by zero | Check the divisor before dividing |
SyntaxError | The code breaks Python's grammar, like a missing colon | Read the line (and the line above) carefully |
ValueError | Right type, wrong content, like int("abc") | Validate input, or use try-except |
AttributeError | The object does not have that method | Check the spelling and the object's type |
ModuleNotFoundError | Python cannot find the module you imported | Fix the name or pip install the package |
In this guide:
How to Read a Python Error Message (Traceback)
When your program crashes, Python prints a traceback. It looks scary, but it has a simple structure, and it usually tells you exactly what went wrong. Here is a small program that works for one student and crashes for the next:
def average(scores):
return sum(scores) / len(scores)
def report(student):
avg = average(student["scores"])
print(f"{student['name']}: {avg:.1f}")
report({"name": "Ana", "scores": [90, 85]})
report({"name": "Ben", "scores": []})
Output:
Ana: 87.5
Traceback (most recent call last):
File "/home/student/py/main.py", line 9, in <module>
report({"name": "Ben", "scores": []})
~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/student/py/main.py", line 5, in report
avg = average(student["scores"])
File "/home/student/py/main.py", line 2, in average
return sum(scores) / len(scores)
~~~~~~~~~~~~^~~~~~~~~~~~~
ZeroDivisionError: division by zero
Read it from the bottom up:
- The last line is the most important. It names the error type (
ZeroDivisionError) and gives a short reason (division by zero). Start here every time. - The lines just above it show where it broke: line 2, inside
average(). The~~~^~~~marks point at the exact part of the line that failed, which is the division. - Everything above that is the path Python took to get there. Line 9 called
report(), and line 5 insidereport()calledaverage(). This tells you where the bad data came from. Ben has an empty list of scores, solen(scores)is 0.
Notice that "Ana: 87.5" printed before the crash. Python ran everything it could until it hit the problem line. Python's error messages have also gotten much friendlier in recent versions. Python 3.10 added hints like "Did you mean...?", and 3.11 added the markers that point at the exact problem, so it pays to read them closely. For more habits that catch bugs before you submit, see our guide on why code submissions fail.
The 3 Types of Errors in Python
Every Python error falls into one of three groups. Knowing which group you are dealing with tells you where to look for the fix.
1. Syntax Errors
A syntax error means your code breaks Python's grammar rules: a missing colon, an unclosed bracket, a misspelled keyword. Python reads the whole file before it runs any of it, so a syntax error stops everything before the first line runs:
print("Start")
print("CodingZap"
print("End")
Output:
File "/home/student/py/main.py", line 2
print("CodingZap"
^
SyntaxError: '(' was never closed
Even though print("Start") is fine, it never printed. Python found the unclosed bracket while reading the file and refused to run any of it. Indentation errors are a special kind of syntax error, so they behave the same way.
2. Runtime Errors (Exceptions)
A runtime error happens while the program is running. The grammar is fine, so Python starts running, but then it hits a line it cannot carry out, like adding a number to a string. Python calls these exceptions:
print("Start")
zap = 5
one = "Coding"
print(zap + one)
print("End")
Output:
Start
Traceback (most recent call last):
File "/home/student/py/main.py", line 4, in <module>
print(zap + one)
~~~~^~~~~
TypeError: unsupported operand type(s) for +: 'int' and 'str'
This time "Start" printed, because everything before line 4 ran normally. NameError, TypeError, IndexError, KeyError, ValueError, and ZeroDivisionError are all runtime errors. These are the ones you can handle with try and except.
3. Logical Errors
A logical error is the sneakiest kind. The program runs, finishes, and prints an answer. The answer is just wrong:
a = 80
b = 90
average = a + b / 2 # should be (a + b) / 2
print("Average:", average)
Output:
Average: 125.0
The average of 80 and 90 is 85, not 125. Python did the division before the addition, so it calculated 80 + 45. There is no error message to help you here. You only catch logical errors by testing your code with inputs where you already know the right answer.
Syntax vs Runtime vs Logical Errors at a Glance
| Criteria | Syntax errors | Runtime errors | Logical errors |
|---|---|---|---|
| Cause | Code breaks Python's grammar rules | An operation fails while running | The program's logic is wrong |
| When you find out | Before any code runs | While the code is running | After it runs, when you check the output |
| What happens | Nothing runs | Runs until the bad line, then stops | Runs to the end with a wrong result |
| Error message? | Yes, with a line number | Yes, a full traceback | No |
| Difficulty to fix | Easy | Medium | Hardest |
| How to fix it | Read the message and fix the code | Fix the cause, or handle it with try-except | Test with known answers, print values, use a debugger |
10 Most Common Python Errors in Student Assignments (and Quick Fixes)
Here are the 10 errors that show up most in student Python assignments. For each one, you get the broken code, the exact message Python prints, the fix, and a few tips so you can avoid it next time.
1. IndentationError
An indentation error happens when your code is not lined up properly. Python uses indentation (the spaces at the start of a line) to decide which lines belong to which block. If the indentation is missing or inconsistent, Python stops before running anything. Most code editors can manage indentation for you, which prevents most of these.
Example:
for i in range(5):
print(i)
Error:
File "/home/student/py/main.py", line 2
print(i)
^^^^^
IndentationError: expected an indented block after 'for' statement on line 1
At a quick glance, this may look fine. But the print(i) line is supposed to run inside the loop, so it needs to be indented. Without the indent, Python does not know what the loop should repeat.
How to fix it:
for i in range(5):
print(i)
You can also get the opposite problem, an indent where Python does not expect one:
name = "Maya"
print(name)
Error:
File "/home/student/py/main.py", line 2
print(name)
IndentationError: unexpected indent
And if you mix tabs and spaces in the same block, Python stops with TabError: inconsistent use of tabs and spaces in indentation. This happens a lot when you copy code from a website or a PDF.
Quick tips:
- Use the same number of spaces for each level of indentation. Four spaces is the Python standard.
- Never mix tabs and spaces. Most editors can turn every tab into spaces for you.
- Let your editor help. VS Code and PyCharm indent new lines automatically and show a guide line for each block.
2. NameError: Name Is Not Defined
A NameError happens when you use a variable or function that does not exist yet. Usually it is a typo, code that runs in the wrong order, or a variable you thought you created but did not.
Example:
print(my_var)
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 1, in <module>
print(my_var)
^^^^^^
NameError: name 'my_var' is not defined
Python raises a NameError because my_var was never created before this line.
How to fix it:
my_var = 10
print(my_var)
Typos cause NameErrors just as often. Newer versions of Python even suggest the name you probably meant:
total_score = 90
print(total_scores)
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 2, in <module>
print(total_scores)
^^^^^^^^^^^^
NameError: name 'total_scores' is not defined. Did you mean: 'total_score'?
Quick tips:
- Define variables before you use them. Python reads your file from top to bottom.
- Watch the spelling and the capitals.
Totalandtotalare two different names. - If a function or variable comes from another file or module, import it first.
math.sqrt()only works afterimport math. - A variable created inside a function does not exist outside it. Return the value from the function instead.
3. TypeError: Unsupported Operand Types
You get this error when you use an operator or function on a type it does not work with. The classic example is using + on a string and a number.
Example:
result = '5' + 10
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 1, in <module>
result = '5' + 10
~~~~^~~~
TypeError: can only concatenate str (not "int") to str
Python does not know whether you want to add the numbers (15) or join the text ("510"), so it refuses to guess. If the number comes first, like 10 + '5', the message reads unsupported operand type(s) for +: 'int' and 'str' instead. Same problem, same fix: convert one side yourself.
How to fix it:
result = int('5') + 10 # math: 15
label = '5' + str(10) # text: '510'
print(result, label)
Output:
15 510
The most common way students hit this is with input(). Whatever the user types comes back as a string, even if it looks like a number:
age = input("Enter your age: ")
print("Next year you will be", age + 1)
What you see:
Enter your age: 19
Traceback (most recent call last):
File "/home/student/py/main.py", line 2, in <module>
print("Next year you will be", age + 1)
~~~~^~~
TypeError: can only concatenate str (not "int") to str
Wrap input() in int() (or float() for decimals) to get a number:
age = int(input("Enter your age: "))
print("Next year you will be", age + 1)
Output:
Enter your age: 19
Next year you will be 20
You will also see TypeError when you call a function with the wrong number of arguments, like TypeError: greet() missing 1 required positional argument: 'name'. The message tells you exactly which argument is missing.
Quick tips:
- Use type conversion when you need it:
int(),float(), orstr(). Our guide to Python data types covers each type and how to convert between them. - Remember that
input()always gives you a string. - When debugging, print
type(variable)right before the line that fails. Very often the variable you thought was anintis actually astr. - f-strings like
f"Total: {total}"let you mix text and numbers without callingstr().
4. IndexError: List Index Out of Range
You will see this error when you ask for a position that does not exist in a list. Usually it means you went past the end of the list without realizing it.
Example:
my_list = [1, 2, 3]
print(my_list[5])
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 2, in <module>
print(my_list[5])
~~~~~~~^^^
IndexError: list index out of range
This crashes because you asked for the item at index 5, but the list only has 3 items (at positions 0, 1, and 2).
How to fix it: check the length first.
my_list = [1, 2, 3]
position = 5
if position < len(my_list):
print(my_list[position])
else:
print("The list only has", len(my_list), "items")
print(my_list[-1]) # -1 always means the last item
Output:
The list only has 3 items
3
In real assignments, the most common cause is a loop that goes one step too far:
scores = [88, 92, 75]
for i in range(len(scores) + 1): # one step too many
print(scores[i])
Output:
88
92
75
Traceback (most recent call last):
File "/home/student/py/main.py", line 3, in <module>
print(scores[i])
~~~~~~^^^
IndexError: list index out of range
The list has 3 items, so the valid indexes are 0, 1, and 2. But range(len(scores) + 1) also produces 3. Use range(len(scores)), or better yet, loop over the items directly with for score in scores:. Our guide to loops in Python shows both styles.
Quick tips:
- List indexes start at 0, not 1. The last item is at
len(my_list) - 1. - Use
my_list[-1]to get the last item without doing any math. - Check the length with
len(my_list)before using an index that comes from user input or a calculation.
5. KeyError: Key Not in Dictionary
A KeyError happens when you ask a dictionary for a key it does not have. Lists give you an IndexError when you go out of range. Dictionaries give you a KeyError when the key is missing. It is a bit like looking up an English word in a Hindi-to-Bengali dictionary. You can flip through every page, but the word is just not in there.
Quick refresher: a dictionary stores pairs, written as key: value inside curly braces. The key is on the left of the colon, and the value is on the right. You look up a value by its key, like student["name"].
Example:
my_dict = {'name': 'Alice'}
print(my_dict['age'])
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 2, in <module>
print(my_dict['age'])
~~~~~~~^^^^^^^
KeyError: 'age'
The last line shows the missing key itself, 'age', which makes this one of the easier errors to track down.
3 ways to fix a KeyError
Fix 1: Check with in before you use the key.
zap = {'Python': 1, 'Java': 2, 'C++': 3}
if 'C' in zap:
print(zap['C'])
else:
print('There is no such key')
Output:
There is no such key
Fix 2: Use .get() with a default value. It returns the value if the key exists, and your default if it does not. It is the shortest fix and usually the best one for optional data.
zap = {'Python': 1, 'Java': 2, 'C++': 3}
print(zap.get('C', 'There is no such key'))
print(zap.get('Java', 'There is no such key'))
Output:
There is no such key
2
Fix 3: Catch it with try-except. Use this when a missing key is a real problem you need to respond to, like a required field missing from a file.
zap = {'Python': 1, 'Java': 2, 'C++': 3}
try:
print(zap['C'])
except KeyError:
print('There is no such key')
Output:
There is no such key
The KeyError in almost every word-counting assignment
Counting things with a dictionary is one of the most common Python assignments, and it almost always starts with this error:
words = ["apple", "banana", "apple"]
counts = {}
for word in words:
counts[word] += 1 # KeyError on the very first word
print(counts)
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 5, in <module>
counts[word] += 1 # KeyError on the very first word
~~~~~~^^^^^^
KeyError: 'apple'
The dictionary starts empty, so counts["apple"] does not exist yet when you try to add 1 to it. Here are two clean fixes:
from collections import Counter
words = ["apple", "banana", "apple"]
# Fix 1: get() with a default of 0
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
print(counts)
# Fix 2: Counter does the counting for you
print(Counter(words))
Output:
{'apple': 2, 'banana': 1}
Counter({'apple': 2, 'banana': 1})
Counter from the collections module was built for exactly this job. defaultdict(int) from the same module works too.
Keys must match exactly
student = {"Name": "Priya", "grade": "A"}
print(student["name"]) # lowercase n
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 2, in <module>
print(student["name"]) # lowercase n
~~~~~~~^^^^^^^^
KeyError: 'name'
Dictionary keys are case-sensitive, and spaces count too. "Name", "name", and "name " are three different keys. When keys come from a file or from user input, clean them first with .strip().lower(). The same thing happens in pandas: df["Score"] raises a KeyError if the column is really called "score" or "Score ". Print df.columns to see the real names. Our Python data cleaning guide shows how to clean up column names.
Quick tips:
- Use
.get()with a default when a key might be missing. - Check whether a key exists with
"key" in my_dictbefore you use it. - If your keys are dynamic or come from users, clean and validate them before using them.
6. ZeroDivisionError: Dividing by Zero
This one is clear-cut. If you divide any number by zero, Python raises a ZeroDivisionError. It usually happens when the number you divide by comes from user input or a calculation you did not check.
Example:
denominator = 0
result = 10 / denominator
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 2, in <module>
result = 10 / denominator
~~~^~~~~~~~~~~~~
ZeroDivisionError: division by zero
Python stops the program here, because dividing by zero is undefined in math, and Python will not let it slide either. The // and % operators raise the same error, and so does dividing a decimal like 1.0 / 0. Some other languages return "infinity" for that last one, but Python does not.
How to fix it: check the divisor first. A classic case is averaging an empty list:
scores = []
if len(scores) > 0:
average = sum(scores) / len(scores)
else:
average = 0
print("No scores yet")
print("Average:", average)
Output:
No scores yet
Average: 0
Quick tips:
- Always check the divisor before dividing, especially when it comes from
len()or user input. - Use an
ifstatement to handle the zero case on purpose. - For harder cases, catch the error with
tryandexcept ZeroDivisionError.
7. SyntaxError: Expected ':'
A missing colon is one of the most common mistakes, and one of the easiest to overlook. Certain Python statements must end with a colon, most often if, for, while, and function definitions. Leave one out and your whole script refuses to run.
Example:
x = 10
if x == 10
print("x is 10")
Error:
File "/home/student/py/main.py", line 2
if x == 10
^
SyntaxError: expected ':'
The ^ points to the exact spot where Python expected the colon.
How to fix it:
x = 10
if x == 10:
print("x is 10")
Two other syntax errors students see all the time:
print("CodingZap"
Error:
File "/home/student/py/main.py", line 1
print("CodingZap"
^
SyntaxError: '(' was never closed
x = 5
if x = 5:
print("five")
Error:
File "/home/student/py/main.py", line 2
if x = 5:
^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
Python 3.10 and later give these clear messages. If a syntax error points at a line that looks fine, check the line above it for an unclosed bracket or quote.
Quick tips:
- Put a colon at the end of every
if,elif,else,for,while,def, andclassline. - Use
==to compare and=to assign. - Your editor usually underlines syntax problems as you type. Do not ignore the red squiggles.
- Reading your code out loud, line by line, is a surprisingly good way to catch small misses like this.
8. ValueError: Invalid Literal
A ValueError happens when a function gets the right type of input, but the value does not make sense. The most common case is converting a string to a number when the string is not a valid number.
Example:
number = int('abc')
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 1, in <module>
number = int('abc')
ValueError: invalid literal for int() with base 10: 'abc'
Python raises a ValueError because 'abc' is a string (the right type for int()), but it is not a number (the wrong content).
How to fix it:
try:
number = int('abc')
except ValueError:
print("Invalid input.")
Output:
Invalid input.
In a real program, you usually want to ask again instead of giving up. This loop keeps asking until the user types a valid number:
while True:
try:
age = int(input("Enter your age: "))
break # valid number, leave the loop
except ValueError:
print("Please type a whole number, like 19.")
print("Thanks! You are", age)
What you see:
Enter your age: nineteen
Please type a whole number, like 19.
Enter your age: 19
Thanks! You are 19
You might be tempted to check the input with isdigit() instead. That gets messy fast. "-5".isdigit() is False even though int("-5") works fine, and so is " 19".isdigit(), even though int() ignores the extra space. Letting int() try and catching the ValueError is simpler and more reliable.
Quick tips:
- Use try-except whenever you convert input you do not control.
- Validate data before converting it, especially if it comes from a user or a file.
- If your input comes from a file or a form, expect it to be messy: extra spaces, empty lines, and stray characters.
9. AttributeError: Object Has No Attribute
This error happens when you call a method or use an attribute that does not exist on the object you have. Usually it means you mixed up two similar types, or you made a typo.
Example:
my_list = [1, 2, 3]
my_list.push(4)
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 2, in <module>
my_list.push(4)
^^^^^^^^^^^^
AttributeError: 'list' object has no attribute 'push'
Python lists do not have a push() method. That is JavaScript. In Python, you call append().
How to fix it:
my_list = [1, 2, 3]
my_list.append(4)
print(my_list)
Output:
[1, 2, 3, 4]
A sneakier version involves None:
names = ["Ben", "Ana"]
names = names.sort() # sort() changes the list and returns None
names.append("Cam")
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 3, in <module>
names.append("Cam")
^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'append'
sort() sorts the list in place and returns None, so names = names.sort() replaces your list with None. The fix is to call sort() without assigning the result, or use sorted(names) if you want a new sorted list:
names = ["Ben", "Ana"]
names.sort() # sorts in place, no assignment
names.append("Cam")
print(names)
Output:
['Ana', 'Ben', 'Cam']
Whenever you see 'NoneType' object has no attribute, look for a variable that got its value from a function that returns nothing. List methods like sort(), append(), and reverse() all return None.
Quick tips:
- Use
dir(object)in the Python shell to see every method and attribute that object has. - Check your spelling and capitals. Python is case-sensitive.
- Make sure you are calling the method on the type you think you have.
print(type(x))helps.
10. ImportError and ModuleNotFoundError: No Module Named...
You usually see this when Python cannot find the module you imported. The name is misspelled, the module does not exist, or you forgot to install a third-party package. In modern Python, it shows up as ModuleNotFoundError, which is a more specific kind of ImportError.
Example:
import maths
Error:
Traceback (most recent call last):
File "/home/student/py/main.py", line 1, in <module>
import maths
ModuleNotFoundError: No module named 'maths'
The built-in module is called math, not maths.
How to fix it:
import math
print(math.sqrt(16))
Output:
4.0
If the module is a third-party package like requests, numpy, or pandas, you have to install it before you can import it: pip install requests.
"But I already installed it!"
This is one of the most common student complaints. Usually, pip installed the package into a different copy of Python than the one running your code. VS Code and PyCharm can each be set to a different Python. The safe way is to install through the same Python that runs your script:
python -m pip install requests
# on Mac or Linux, you may need:
python3 -m pip install requests
In VS Code, check the Python version shown in the status bar at the bottom of the window (or run "Python: Select Interpreter") and make sure it is the one you installed into.
Do not name your file after a module
If you save your own file as random.py, turtle.py, or csv.py, Python imports your file instead of the real module. Here is what Python 3.13 printed when a student's file named random.py ran import random and then random.randint(1, 6):
AttributeError: module 'random' has no attribute 'randint' (consider renaming '/home/student/py/random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)
Older versions of Python say partially initialized module 'random' has no attribute 'randint' (most likely due to a circular import), which is much more confusing. Either way, rename your file, and delete the __pycache__ folder next to it if one exists.
Quick tips:
- Double-check the spelling and capitals of the module name.
- Install external packages with
python -m pip install package_name. - Run
python -m pip listto see which packages are installed for the Python that runs your code.
How to Handle Errors With try and except in Python
Try-except is Python's built-in safety net. It lets your program survive runtime errors instead of crashing. You wrap risky code inside a try block, and if Python hits an error, it jumps to your except block, where you decide what happens next. Here is the smallest useful example:
try:
age = int(input("Enter your age: "))
print(f"You are {age} years old")
except ValueError:
print("That was not a valid number")
What you see when the user types "hello":
Enter your age: hello
That was not a valid number
Without the try-except, typing "hello" instead of a number would crash the whole program. With it, the user gets a friendly message and your program keeps running. That idea is behind almost every program that deals with real users, real files, or the internet.
How try-except actually works
Most beginners learn try-except as a magic spell that prevents crashes. That is only half true, and the full picture is more useful.
Python runs your code line by line. The moment something goes wrong (a missing file, a bad conversion, an empty list), Python creates an exception object that holds the details. Without a try-except, that exception travels up through every function that called the failing line until it reaches the top of your program. Then Python prints the traceback and quits. A try-except catches the exception on its way up.
The full syntax has four parts. Most students only know two:
try:
# Code that might fail
risky_thing()
except SomeError:
# Runs only if SomeError happens in try
handle_it()
else:
# Runs only if no error happened
celebrate()
finally:
# Runs no matter what
clean_up()
Only try is always required, plus at least one except or a finally. You cannot use else without an except. The else block runs when everything went smoothly. The finally block runs whether things broke or not, which makes it the right place for cleanup work like closing files. Here is a real example that uses all four:
try:
file = open("report.txt", "r")
except FileNotFoundError:
print("Report file is missing")
else:
content = file.read()
file.close()
print(f"Read {len(content)} characters successfully")
finally:
print("Done attempting to read the file")
Output when report.txt does not exist:
Report file is missing
Done attempting to read the file
If the file exists, you would see the "Read ... characters successfully" message instead, followed by the same "Done" message. The finally block always runs.
Open files safely with with
For files, pair try-except with a with statement. with closes the file for you automatically, even if something goes wrong while reading:
try:
with open("data.txt", "r") as file:
content = file.read()
print(content)
except FileNotFoundError:
print("Could not find data.txt, please check the file path")
Output:
Could not find data.txt, please check the file path
FileNotFoundError only covers a missing file. If the file exists but you do not have permission to read it, you get PermissionError instead. Both are kinds of OSError, so you can catch the parent class to handle most problems with opening a file:
try:
with open("data.txt", "r") as file:
content = file.read()
except OSError as e:
print(f"Could not open the file: {e}")
Catch more than one error
You can list several except blocks after one try, one for each error that needs a different response:
def safe_divide(a, b):
try:
return int(a) / int(b)
except ValueError:
return "Both values must be whole numbers"
except ZeroDivisionError:
return "You cannot divide by zero"
print(safe_divide("10", "4"))
print(safe_divide("10", "zero"))
print(safe_divide("10", "0"))
Output:
2.5
Both values must be whole numbers
You cannot divide by zero
Python checks the except blocks from top to bottom and runs the first one that matches, so list the most specific errors first. If two errors need the same response, you can group them: except (ValueError, TypeError):.
Get the error message with as e
Add as e to capture the exception object, then print it to see the message Python would have shown:
try:
int("abc")
except ValueError as e:
print(f"Error details: {e}")
Output:
Error details: invalid literal for int() with base 10: 'abc'
Raise your own errors
You can also signal errors in your own functions with raise. This is how you stop bad data at the door instead of letting it cause a confusing crash later:
def set_grade(score):
if not 0 <= score <= 100:
raise ValueError(f"Score must be between 0 and 100, got {score}")
return score
try:
set_grade(105)
except ValueError as e:
print("Problem:", e)
Output:
Problem: Score must be between 0 and 100, got 105
In bigger projects, you can create your own exception classes by inheriting from Exception. The name of the class then explains the problem on its own:
class InsufficientFundsError(Exception):
"""Raised when a withdrawal is bigger than the balance."""
def withdraw(balance, amount):
if amount > balance:
raise InsufficientFundsError(f"Balance is {balance}, tried to take {amount}")
return balance - amount
try:
withdraw(50, 80)
except InsufficientFundsError as e:
print("Transaction blocked:", e)
Output:
Transaction blocked: Balance is 50, tried to take 80
What try-except cannot catch
Students often ask, "Why doesn't my try-except catch this?" Look at this:
try:
print("Hello"
except SyntaxError:
print("Caught it")
Error:
File "/home/student/py/main.py", line 2
print("Hello"
^
SyntaxError: '(' was never closed
The except SyntaxError line never gets a chance to run. Syntax errors and indentation errors in your file stop Python while it is still reading the code, before anything runs, so there is nothing for try-except to catch. The only fix is to correct the code itself.
Try-Except Best Practices
You now know the syntax and the 10 errors. The difference between a beginner and a pro using try-except comes down to a few habits.
Be specific. Never use a bare except.
# Avoid
try:
risky_operation()
except:
pass
# Prefer
try:
risky_operation()
except ValueError:
print("Invalid value")
A bare except: catches everything, including KeyboardInterrupt (when the user presses Ctrl+C) and SystemExit. Add pass and it hides every bug in that block. You almost never want that.
Catch what you can handle, and let the rest crash. If you do not know how to recover from an error, do not catch it. Let it crash, read the traceback, and fix the real bug. Catching an exception just to print "something went wrong" is worse than crashing, because the traceback would have told you exactly what was wrong.
Keep the try block small.
# Avoid: too much inside try
try:
data = load_data()
cleaned = clean_data(data)
save_results(cleaned)
except Exception:
print("Something failed")
# Prefer: wrap only the step that can fail
def run_report():
try:
data = load_data()
except FileNotFoundError:
print("Data file missing")
return
cleaned = clean_data(data)
save_results(cleaned)
Smaller try blocks tell you exactly what failed and let you respond differently to different failures.
Use else for the success path. Code that should run only if the try worked belongs in else, not at the bottom of the try block. That way, an error in the success code does not get caught by mistake:
try:
score = int(text)
except ValueError:
print("Not a number")
else:
print("Doubled:", score * 2)
Use finally (or with) for cleanup. If you open a file, a network connection, or a database, make sure it gets closed in finally. Even better, use a with statement, which does the cleanup for you.
Log errors in bigger projects. For real projects, use the logging module instead of print(). It records a severity level with each message, can add timestamps once you set it up (for example with logging.basicConfig()), and can write to a file:
import logging
try:
process_order(order_id)
except KeyError as e:
logging.error(f"Missing field in order {order_id}: {e}")
When Try-Except Is the Wrong Answer
Try-except is a tool, not a default. Sometimes reaching for it makes your code worse.
Do not use it for conditions you can simply check.
# Avoid this
try:
value = my_dict["key"]
except KeyError:
value = "default"
# Use this instead
value = my_dict.get("key", "default")
The try part costs almost nothing when no error happens. But raising and catching an exception is slower than a normal if check, because Python has to build the exception object and search for a handler. For conditions you expect to happen often, like "this key might be missing," use the feature built for it.
Do not use it to hide bugs you should fix.
try:
print(total)
except NameError:
total = 0
print(total)
This technically "works," but it hides the real problem. If total was supposed to be defined earlier, you have a bigger bug that the try-except is covering up. NameError, AttributeError from a typo, and IndentationError are code problems. Fix them in the code.
Do not catch Exception without thinking. except Exception: pass catches almost every error there is, including the bugs you would want to know about. Be specific about what you expect.
Do not stack try blocks inside try blocks. Deeply nested try-except code gets hard to read and hard to debug. If you need several, split the work into small functions, each with its own simple try-except.
Let tests and scripts fail loudly. When you are testing, you want errors to crash so you notice them. Quietly catching errors can let bad data slip through unnoticed.
Before you add a try-except, ask yourself: "If this fails, what should the program do differently from crashing?" If the honest answer is "nothing, I just do not want to see the error," you do not need try-except. You need to fix the underlying problem.
Conclusion
You will run into plenty of errors as a Python programmer, and every one of them has a fix once you know what to look for. Recognizing the most common Python errors early will save you hours on simple bugs and leave you more time to build things that actually work.
To strengthen your Python skills and avoid repeating the same mistakes, try some of these beginner-friendly Python project ideas. Building small projects is the fastest way to make these fixes second nature. And before you hand anything in, run through our checklist before a programming assignment submission.
Key takeaways:
- Python error messages usually tell you exactly what went wrong. Read the last line of the traceback first.
- Syntax errors stop the whole file before it runs, runtime errors stop at the bad line, and logical errors do not stop anything. They just give wrong answers.
- Most student errors come down to details: indentation, colons, data types, and exact names.
- Test small chunks of code as you write them, so you catch problems right away instead of all at once.
- Use try-except for things outside your control, like user input, files, and network calls. Fix everything else at the source.
- When you are stuck, ask for help from a classmate, your instructor, or a tutor. Every bug you fix makes the next one faster.
Keep practicing, test your code often, and do not be afraid to break things. That is how everyone learns to code. If a Python error just will not go away, our online Python tutors can debug it with you and explain the fix in plain English.
Frequently Asked Questions
1. What are the main types of errors in Python?
There are three: syntax errors (the code breaks Python's grammar rules and nothing runs), runtime errors, also called exceptions (the program crashes partway through, like a TypeError or KeyError), and logical errors (the program runs but gives the wrong answer).
2. What is the most common error in Python for beginners?
Beginners usually hit IndentationError and SyntaxError (like a missing colon) first, because Python is strict about both. Once the code runs, NameError, TypeError, IndexError, and KeyError are the errors students see most.
3. How do I read a Python traceback?
Start at the last line. It names the error type and gives a short reason. The lines just above it show the file, line number, and code where the error happened. The lines above that show which function calls led there, which helps you find where the bad data came from.
4. How do I fix a KeyError in Python?
Check that the key exists with if key in my_dict, use my_dict.get(key, default) to get a default value instead of an error, or catch it with try and except KeyError. Also check the exact spelling, capitals, and spaces in the key.
5. Why do I get ModuleNotFoundError when the package is already installed?
pip probably installed the package into a different Python than the one running your code. Install it with python -m pip install package_name using the same Python, and check which interpreter your editor is set to use. Also make sure none of your own files has the same name as the module.
6. Can try-except catch every type of Python error?
No. Try-except only catches errors that happen while your code is running. It cannot catch a SyntaxError or IndentationError in the same file, because those stop Python before your code starts running. You have to fix those in the code itself.
7. Should I always use try-except with user input?
Yes for conversions like int(input()) and float(input()), where invalid input is common. For other checks, a simple if is often cleaner. A good rule: use try-except when the failure is hard to predict, and use if checks when it is easy to predict.
8. What is the difference between except Exception and a bare except?
A bare except: catches absolutely everything, including Ctrl+C (KeyboardInterrupt) and SystemExit. except Exception: catches normal errors but lets those through, which is usually what you want. Both are too broad for most cases, so catch specific errors whenever you can.
9. Can I have multiple except blocks for one try?
Yes, and you should when different errors need different responses. List them from most specific to least specific. Python checks each except in order and runs the first one that matches.
10. How do I get the actual error message inside except?
Use the as keyword: except ValueError as e:. The variable e holds the exception, and printing it shows the same message Python would have displayed.
11. Is try-except slow in Python?
The try part costs almost nothing when no error happens. The cost comes when an exception is actually raised, because Python has to build the exception object and find a matching handler. That is fine for rare errors, but for conditions that happen often, an if check or .get() is faster.
12. Can I raise my own exceptions in Python?
Yes, with the raise keyword, for example raise ValueError("Score must be between 0 and 100"). You can also create your own exception classes by inheriting from Exception, which is common in larger projects.
13. What does else do in a try-except block?
Code in else runs only if no exception happened in try. You could put that code at the end of the try block instead, but then any error it raises would be caught by your except by mistake. Using else keeps the code that might fail separate from the code that should not be wrapped.
