Skip to content

ይህ ትምህርት ገና ወደ አማርኛ አልተተረጎመም፤ ስለዚህ በእንግሊዝኛ ቀርቧል። የእንግሊዝኛውን ገጽ ክፈቱ

try, except, else, finally

4 min read

Some errors you can see coming: a user types five where you asked for a number. You don't want the program to stop for that. You want it to say something useful and carry on. By the end of this lesson you'll handle an error on purpose and know exactly where your program continues afterwards.

Catching an error

int() can't convert five, so this program stops with a traceback:

age = int(input("Age: "))
print("Next year you'll be", age + 1)

In the editor, press Escape then Tab to move on.

One answer per line, given to input() in order.

Put the line that might fail inside try, and say what to do in except:

text = input("Age: ")
try:
    age = int(text)
    print("Next year you'll be", age + 1)
except ValueError:
    print("That's not a whole number.")
print("Done")

In the editor, press Escape then Tab to move on.

One answer per line, given to input() in order.

Python runs the block. If a line in it raises a ValueError, Python jumps to the block for that type. That's how you an error, also called catching it. Change the Input to 17 and run it again: the except block is skipped.

Where does the program go after the except? Predict:

ውጤቱን ገምቱ

Decide before you look. Guessing wrong is how this sticks.

try:
    print("start")
    number = int("five")
    print("converted")
except ValueError:
    print("handled")
print("after")
Pick the output

Python prints

start
handled
after

The error on line 3 ends the try block on the spot, so 'converted' never prints. After the except block, Python carries on after the whole try statement: 'after'.

If you picked the first answer, you pictured Python going back to finish the try block. It never does: the rest of the try block is skipped, and once the except block is done, the program continues after the whole statement. The line that failed never finished, so its assignment never happened. Predict:

ውጤቱን ገምቱ

Decide before you look. Guessing wrong is how this sticks.

try:
    age = int("five")
except ValueError:
    print("Not a number")
print(age)

Python prints

Not a number
Traceback (most recent call last):
  File "<your code>", line 5, in <module>
    print(age)
          ^^^
NameError: name 'age' is not defined

int('five') failed, so 'age = ...' never finished and the name age was never made. The except printed its message, then line 5 asked for a name that doesn't exist. If you pictured try as a safe place where age gets some value anyway, this is the surprise.

If age had a value before the try (say age = 0 above it), the last line would print 0: the name keeps its old value, because the failed assignment never happened.

Always name the error

except: with no type catches every error, including your own typos:

else and finally

A try statement can have two more blocks. Predict the order:

ውጤቱን ገምቱ

Decide before you look. Guessing wrong is how this sticks.

try:
    print("start")
    int("five")
except ValueError:
    print("handled")
else:
    print("no error")
finally:
    print("finally")
print("after")
Pick the output

Python prints

start
handled
finally
after

There was an error, so else is skipped: else runs only when the try block had no error. finally runs either way.

The block runs only when the try block had no error, like a loop's else, which runs only when there was no break (lesson 3.3). The block always runs: with no error, with an error that's handled, and even with one no except catches, where it runs just before the program stops with the traceback. It's for cleaning up, like closing a file (lesson 8.1).

Why not put "no error" code at the end of the try block? An error there would be caught by an except meant for something else. else keeps try to the line that might fail.

ጥያቄ

When does the else of a try run?

Validation done right

Lessons 3.5 and 5.8 checked text with isdigit() before converting. That's wrong in both directions. It turns away text int() accepts:

print(int(" 5 "), int("-5"))
print(" 5 ".isdigit(), "-5".isdigit())

In the editor, press Escape then Tab to move on.

And it lets through ፩, which int() can't convert (lesson 6.3), so 5.8's ask_number still stops with a ValueError if someone types it. The honest test is to try int() itself. Here's ask_number from lesson 5.8, rewritten with try. With isdigit(), it could never accept a temperature of -3:

def ask_number(prompt, low, high):
    while True:
        text = input(prompt)
        try:
            number = int(text)
        except ValueError:
            number = None
        if number is not None and low <= number <= high:
            return number
        print(f"Please enter a number from {low} to {high}.")

print(ask_number("Temperature: ", -10, 45))

In the editor, press Escape then Tab to move on.

One answer per line, given to input() in order.

There are names for the two styles. , "easier to ask forgiveness than permission", tries and handles the error. , "look before you leap", checks first. For conversions, EAFP is usually right: int() knows exactly what it accepts. LBYL is fine for simple checks, like if key in prices.

An error raised inside a function can be caught by the code that called it. to_age doesn't catch it, so it goes up to the global code, which does:

Caught by the caller

Press Next to run one line at a time. Each arrow shows the object a name refers to. Each call gets its own frame of names, below the frame that called it.

def to_age(text):
return int(text)
try:
age = to_age("five")
except ValueError:
print("Not a number")

Frames, oldest first: global.

Step 1 of 7

Step 1 of 7. Line 1: def to_age(text):. Nothing in memory changed.

መልመጃ

A safe to_int

Write to_int(text): return the whole number in text, or None if int() can't convert it. repr (lesson 6.1) shows each test's quotes and spaces.

Output
'42' -> 42
' 5 ' -> 5
'-5' -> -5
'5.5' -> None
'' -> None
'፩' -> None

Your code

def to_int(text):
    # Try int(text); return None if it raises ValueError
    pass

for text in ["42", " 5 ", "-5", "5.5", "", "፩"]:
    print(repr(text), "->", to_int(text))

In the editor, press Escape then Tab to move on.

መፍትሄውን አሳይ

This is one way to solve it, not the only one. If yours prints the same thing, it works.

def to_int(text):
    try:
        return int(text)
    except ValueError:
        return None

for text in ["42", " 5 ", "-5", "5.5", "", "፩"]:
    print(repr(text), "->", to_int(text))

ዋና ዋና ነጥቦች

  • try / except ValueError: handles an error you expect; the program continues after the whole try statement.
  • The rest of the try block is skipped, and an assignment that failed never happened.
  • Always name the error type: a bare except: hides your own bugs.
  • else runs only when there was no error; finally always runs.
  • EAFP (try it) suits conversions; LBYL (check first) suits simple checks. An error from a function can be caught by its caller.