Handling errors with try and except
Last lesson was about reading errors. This one is about planning for them. Some errors are bugs you should fix. Others are things that will happen no matter how good your code is: someone types "twelve" when you asked for a number, or divides by a friend count that turns out to be zero.
For those, Python lets you say "try this, and if it goes wrong in this specific way, do that instead":
text = "twelve"
try:
age = int(text)
print("Next year you will be", age + 1)
except ValueError:
print("That was not a whole number.")
Python runs the try block. The moment a line inside it raises an error, it stops right there and jumps to the matching except block. If nothing goes wrong, the except block is skipped completely. Either way, the program keeps going afterwards instead of crashing.
Always name the error you expect. except ValueError: catches exactly the "that is not a number" problem. A bare except: catches everything, including your own typos, which turns a clear NameError into a silent mystery. Catch what you can actually deal with, and let the rest crash loudly so you can fix it.
You can have more than one except, and you can grab the error message with as:
try:
result = 10 / int(text)
except ValueError:
print("Not a number")
except ZeroDivisionError as e:
print("Maths problem:", e)
Two optional extras: else runs only when the try block had no error, and finally runs no matter what. You will see finally used to tidy up, like closing a file.
A handy pattern is a function that returns a safe default when the input is bad, so the code that calls it never has to worry.
Try it yourself
Edit it. Break it. Run it again.answers = ["14", "fifteen", "16", "", "17.5"]
for text in answers:
try:
age = int(text)
except ValueError:
print(repr(text), "is not a whole number, skipping it")
else:
print(repr(text), "is fine, next year:", age + 1)
try:
print(10 / 0)
except ZeroDivisionError as e:
print("Caught it:", e)
finally:
print("This line always runs")
Your turn
Type it yourself. That is the whole trick.1Safe number
Write to_int(text) that returns the text converted to a whole number, or returns 0 if the text is not a whole number. It must not crash.
def to_int(text):
return int(text)
2Share the pizza
Write slices_each(slices, people) that returns how many whole slices each person gets (use //). If people is 0, return 0 instead of crashing. Catch only the error that dividing by zero raises.
def slices_each(slices, people):
return slices // people