Catching Errors with try and except
About 15 minutes
Why this matters
So far an error has meant a crash. Real programs meet bad input, missing files and surprises all the time, and a good program decides what to do about them instead of dying. Python lets you catch an error and carry on.
The idea
text = "abc"
try:
number = int(text) # Python tries this...
except ValueError: # ...and if a ValueError happens, jumps here
number = 0
print(number) # 0
Name the kind of error you expect. Catching too much hides real bugs. A few more parts:
try:
price = float(text)
except ValueError as err: # "as err" keeps the error so you can show it
print("Not a number:", err)
else: # runs only if nothing went wrong
print("Price is", price)
finally: # always runs, error or not
print("done")
One clause can catch several kinds: except (ValueError, TypeError):.
Try it
Run the example with text = "4.5", then "abc", then "". Which of else and finally ran each time? Then try int(None) inside the try: that is a TypeError, so the except ValueError clause does not catch it.
Your turn
Write three functions:
to_int(text, default=0): returnint(text), ordefaultif the text is not a whole number. Anything that is not aValueErrorshould still crash (for exampleto_int(None)raises aTypeError).safe_divide(a, b): returna / b, orNonewhenbis zero.get_age(person):personis a dictionary. Returnint(person["age"]). If there is no"age"key return"unknown". If the value cannot be turned into a whole number (text like"abc", orNone) return"invalid".
Recap
tryruns code that might fail;except SomeErrorhandles that one kind of failure.- Catch the specific errors you expect so real bugs still show up.
elseruns when nothing failed;finallyalways runs.
Common mistakes
- A bare
except:that catches everything. It even hides typos (NameError). Name the error. - Putting too much inside
try. Keep it to the lines that can actually fail. - Forgetting the colon or indentation after
try:/except ...:, which gives aSyntaxErrororIndentationError.