Python Exceptions: try, except, else and finally
1Python Try...Except: overview
An exception is Python's signal that something went wrong while the program was running. If nothing handles it the program stops, but a try/except block lets you catch it and recover.
Before this lesson: Python if, elif and else, Python Functions
2Python Try...Except: diagram
3Python Try...Except: explained step by step
Some problems only show up while a program is running: turning "abc" into a number, dividing by zero, reading a file that isn't there. Python reports each one by raising an exception, an object that describes what went wrong. If nothing handles it, the program stops and prints a traceback.
Reading a traceback
Traceback (most recent call last):
File "main.py", line 4, in <module>
print(average([]))
~~~~~~~^^^^
File "main.py", line 2, in average
return sum(numbers) / len(numbers)
~~~~~~~~~~~~~^~~~~~~~~~~~~~
ZeroDivisionError: division by zero
Read it from the bottom up. The last line says what happened: the exception type (ZeroDivisionError) and a message. The lines above say where: each File ..., line ... entry is one step in the chain of function calls, with the most recent call at the bottom. Here line 4 called average([]), and line 2 inside it divided by len([]), which is 0. The ^ and ~ markers point at the exact expression that failed.
Catching an exception with try/except
Put the risky code in a try block and say what to do instead in an except block. If the try block succeeds, the except block is skipped.
def to_number(text):
try:
return int(text)
except ValueError:
print(f"{text!r} is not a whole number, using 0")
return 0
print(to_number("42"))
print(to_number("forty"))Always name the exception you expect. A bare except: catches everything, including typos in your own code, which turns easy bugs into mysteries.
Several excepts, else and finally
def safe_divide(a, b):
try:
result = a / b
except ZeroDivisionError:
print("Cannot divide by zero")
except TypeError as err:
print("Bad value:", err)
else:
print("Result:", result)
finally:
print("-- finished", a, "/", repr(b))
safe_divide(10, 4)
safe_divide(10, 0)
safe_divide(10, "2")- Python checks the
exceptblocks from top to bottom and runs the first one that matches. To handle several types the same way, list them in a tuple:except (ValueError, TypeError):. as errstores the exception object, so you can print its message.elseruns only if thetryblock raised nothing. It lets you keep thetryblock down to the one line that might fail.finallyruns no matter what: after success, after a handled error, even after an error nobody catches. Use it for clean-up such as closing a file.
Raising your own exceptions
When your code spots a problem it can't sensibly fix, such as a negative amount, use raise to report it. For errors that belong to your program, create your own exception type. You don't need to know classes yet: the two-line class below is all it takes.
class InsufficientFundsError(Exception):
pass
def withdraw(balance, amount):
if amount <= 0:
raise ValueError("amount must be positive")
if amount > balance:
raise InsufficientFundsError(f"balance is only {balance}")
return balance - amount
for amount in [30, 500, -5]:
try:
print("New balance:", withdraw(100, amount))
except (ValueError, InsufficientFundsError) as err:
print(type(err).__name__ + ":", err)Quick reference: Python Try...Except
- How to Check if a File Exists in Python — Use `pathlib`: `Path("data.txt").is_file()` is `True` only if the path exists and is a regular file. `Path(..…
- How to Convert a String to a Datetime in Python — Use `datetime.strptime(text, format)`, for example `datetime.strptime("2026-03-15", "%Y-%m-%d")`. For ISO 860…
4Python Try...Except: syntax
try:
risky_code()
except SomeError as err: # runs if SomeError happens
handle(err)
except (ErrorA, ErrorB): # several types at once
handle_other()
else: # runs only if nothing was raised
use_result()
finally: # always runs
clean_up()
raise ValueError("message") # signal a problem yourself
5Python Try...Except: run the example
Press Run (or Ctrl + Enter). The output (step 6) appears directly below the code. Change anything and run it again.
def parse_quantity(text):
qty = int(text)
if qty < 0:
raise ValueError("quantity cannot be negative")
return qty
orders = ["3", "two", "5", "-1"]
total = 0
for text in orders:
try:
qty = parse_quantity(text)
except ValueError as err:
print(f"Skipped {text!r}: {err}")
else:
total += qty
print(f"Added {qty}")
print("Total items:", total)Expected outputAdded 3
Skipped 'two': invalid literal for int() with base 10: 'two'
Added 5
Skipped '-1': quantity cannot be negative
Total items: 8
7Python Try...Except: how the example works
Hover or tap a step to highlight its lines in the example above.
- Line 1-5
parse_quantity()turns text into a whole number.int()raisesValueErrorby itself for text like"two", and the function raises its ownValueErrorfor negative numbers. - Line 7-8The orders arrive as strings, as if typed into a web form.
totalstarts at 0. - Line 10-12The call that might fail sits inside
try, so a bad order can't crash the whole loop. - Line 13-14
except ValueError as errcatches both kinds of problem.errholds the exception, and printing it shows its message. The loop then moves on to the next order. - Line 15-17
elseruns only when thetryblock succeeded, so only valid quantities are added to the total. - Line 19After the loop the total is 3 + 5 = 8. Two orders were rejected, but the program kept running to the end.
8Python Try...Except: common mistakes
Using a bare except that hides real bugs
✗ Wrong
def average(nums):
try:
return sum(nums) / len(numbers)
except:
return 0
print(average([4, 6]))✓ Right
def average(nums):
try:
return sum(nums) / len(nums)
except ZeroDivisionError:
return 0
print(average([4, 6]))Catch only the exception you expect (here ZeroDivisionError for an empty list). Unexpected errors such as typos will then show up with a clear traceback.
Using a variable that the failed try never created
✗ Wrong
try:
result = 10 / 0
except ZeroDivisionError:
print("Something went wrong")
print(result)✓ Right
try:
result = 10 / 0
except ZeroDivisionError:
print("Something went wrong")
result = None
print(result)When the line in try fails, the assignment never happens. Give the variable a fallback value inside except, or only use it in an else block.
Catching the wrong exception type
✗ Wrong
try:
age = int("twelve")
except TypeError:
print("Please type a number")✓ Right
try:
age = int("twelve")
except ValueError:
print("Please type a number")int() with text that isn't a number raises ValueError, not TypeError. Read the last line of the traceback to learn the real exception type, then catch that one.
9Python Try...Except: exercises
Write your answer, then press Check. The checks run in your browser.
1. A safe number converter
Write code Easy ✓ CompletedChange safe_int(text) so it returns int(text) when the text is a whole number, and returns None instead of crashing when it isn't. For example safe_int("12") is 12 and safe_int("hello") is None.
def safe_int(text):
# return None if text is not a whole number
return int(text)
print(safe_int("12"))def safe_int(text):
try:
return int(text)
except ValueError:
return None
print(safe_int("12"))
2. Predict the order
Predict the output Medium ✓ CompletedRead the code and type exactly what it will print. Pay attention to which blocks run for each call. Then press Check to compare.
def check(value):
try:
number = 100 / value
except ZeroDivisionError:
print("A")
else:
print("B", number)
finally:
print("C")
check(4)
check(0)B 25.0
C
A
C
2 more exercises → 4 more examples
Questions learners ask
Should I use a bare except or except Exception?
Neither, if you can avoid it. Catch the specific exception you expect, such as ValueError or KeyError, so unexpected bugs still show up. A bare except: is the worst choice because it also catches things like KeyboardInterrupt. If you really need a catch-all, use except Exception as err: and at least print or log err.
What is the difference between else and finally in try/except?
else runs only when the try block finished without an exception, so it is the place for code that depends on the try succeeding. finally runs every time: after success, after a handled exception and even when an exception is not caught. Use finally for clean-up such as closing files.
When should I raise an exception instead of returning None?
Raise an exception when the caller cannot sensibly continue, for example a negative price or a missing required setting. Returning None is easy to forget to check, and the program then fails later with a confusing TypeError far from the real cause. An exception stops at the exact spot and explains the problem.
Further reading
10Next lesson
Up nextPython TypeError: What It Means and How to Fix ItA TypeError means Python was asked to do something with a value whose type doesn't support it, such as adding a number …Related:
Python TypeError: What It Means and How to Fix ItPython KeyError: What It Means and How to Fix ItPython IndexError: list index out of rangePython File Handling
← Python datetime Module · All Errors and Exceptions lessons · Practise in the IDE