Skip to content
Laviyx Learn

Try

Python course menu

Python Exceptions: try, except, else, finally and raise

Learn Python exception handling: read tracebacks, catch errors with try/except, handle specific exceptions, use else and finally, access the error message, raise your own exceptions, and create custom exception classes.

Intermediate9 min readUpdated
On this page

Things go wrong in real programs: a user types letters instead of a number, a file is missing, a website does not respond. When Python hits an error it cannot handle, it raises an exception, and if nothing catches it, the program stops. Exception handling lets your program respond sensibly instead of crashing.

An unhandled exception#

Python
print(10 / 0)
Output
ZeroDivisionError: division by zero

The last line of the traceback names the exception type (ZeroDivisionError) and a message.

try and except#

Put code that might fail in a try block, and the response in an except block:

Python
try:
    result = 10 / 0
except ZeroDivisionError:
    print("You can't divide by zero")

print("Program continues")
Output
You can't divide by zero
Program continues

When the error happens, Python jumps straight to the matching except block, and the program keeps running afterwards.

A practical example: user input#

Python
try:
    age = int(input("Age: "))
    print(f"Next year: {age + 1}")
except ValueError:
    print("Please enter a whole number")
Output
Age: abc
Please enter a whole number

Common exception types#

ExceptionTypical cause
ValueErrorright type, wrong value: int("abc")
TypeErrorwrong type: "a" + 1
ZeroDivisionErrordividing by zero
KeyErrormissing dictionary key
IndexErrorlist index out of range
FileNotFoundErroropening a file that does not exist
AttributeErrorusing a method or attribute that does not exist
NameErrorusing a variable that was never defined
Python
data = {"name": "Asha"}
try:
    print(data["email"])
except KeyError as e:
    print("Missing key:", e)

items = [1, 2]
try:
    items[5]
except IndexError as e:
    print("IndexError:", e)
Output
Missing key: 'email'
IndexError: list index out of range

Getting the error message#

except SomeError as e stores the exception object in e:

Python
try:
    int("xyz")
except ValueError as e:
    print("Error:", e)
    print(type(e).__name__)
Output
Error: invalid literal for int() with base 10: 'xyz'
ValueError

Several excepts, else and finally#

Python
def safe_divide(a, b):
    try:
        result = a / b
    except ZeroDivisionError:
        return None
    except TypeError:
        return "numbers only"
    else:
        return round(result, 2)      # only if no exception happened
    finally:
        print(f"divide({a!r}, {b!r}) attempted")   # always runs

print(safe_divide(10, 3))
print(safe_divide(1, 0))
print(safe_divide("a", 2))
Output
divide(10, 3) attempted
3.33
divide(1, 0) attempted
None
divide('a', 2) attempted
numbers only
BlockRuns when…
tryalways (until an error occurs)
except Xan exception of type X occurred
elseno exception occurred
finallyalways, even after return, used for clean-up

You can also catch several types in one block: except (ValueError, TypeError):.

Keep going after bad data#

Handling errors inside a loop lets you skip bad items and process the rest:

Python
values = ["10", "x", "30", "", "5"]
total = 0
bad = []

for v in values:
    try:
        total += int(v)
    except ValueError:
        bad.append(v)

print(total, bad)
Output
45 ['x', '']

Raising exceptions#

Your own functions can raise exceptions when they receive invalid input:

Python
def withdraw(balance, amount):
    if amount > balance:
        raise ValueError(f"Insufficient funds: balance {balance}, requested {amount}")
    return balance - amount

print(withdraw(500, 200))

try:
    withdraw(500, 900)
except ValueError as e:
    print(e)
Output
300
Insufficient funds: balance 500, requested 900

Raising an exception is often better than returning a special value like None, because the caller cannot accidentally ignore it.

Custom exceptions#

Define your own exception type by creating a class that inherits from Exception:

Python
class InsufficientFundsError(Exception):
    pass

try:
    raise InsufficientFundsError("Balance too low")
except InsufficientFundsError as e:
    print(f"{type(e).__name__}: {e}")
Output
InsufficientFundsError: Balance too low

Custom types let callers catch exactly the errors they expect. You will learn about classes in OOP.

Common mistakes#

Practice#

Practice exercise

Write read_number(text) that returns the text converted to a float, or None if it is not a valid number. Test it on "3.5", "-2", "abc" and "1e3".

Show hint

Return float(text) inside try, and None in except ValueError.

Show solution
Python
def read_number(text):
    try:
        return float(text)
    except ValueError:
        return None

for t in ["3.5", "-2", "abc", "1e3"]:
    print(t, read_number(t))
Output
3.5 3.5
-2 -2.0
abc None
1e3 1000.0

"1e3" is scientific notation for 1,000, which float() understands.

Key takeaway#

Finished this lesson?