Skip to content

Python Error Handling: Try, Except, Finally

Errors happen. Python’s exception handling lets you manage them gracefully.

Basic Try-Except

try:
    number = int(input("Enter a number: "))
    result = 10 / number
    print(f"Result: {result}")
except ValueError:
    print("That's not a valid number!")
except ZeroDivisionError:
    print("Can't divide by zero!")

Catching Multiple Exceptions

try:
    value = int("abc")
    result = 10 / 0
except (ValueError, ZeroDivisionError) as e:
    print(f"Error occurred: {e}")

Catching All Exceptions

try:
    risky_operation()
except Exception as e:
    print(f"Something went wrong: {e}")

Use this sparingly. Catch specific exceptions when you know what might go wrong.

Try-Except-Else-Finally

try:
    file = open("data.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("File not found!")
else:
    # Runs only if no exception occurred
    print(f"Read {len(content)} characters")
finally:
    # Always runs, even if exception
    file.close()

Raising Exceptions

def withdraw(balance, amount):
    if amount <= 0:
        raise ValueError("Withdrawal amount must be positive")
    if amount > balance:
        raise ValueError("Insufficient funds")
    return balance - amount

try:
    new_balance = withdraw(100, 200)
except ValueError as e:
    print(f"Withdrawal failed: {e}")

Custom Exceptions

class InsufficientFundsError(Exception):
    pass

class NegativeAmountError(Exception):
    pass

class BankAccount:
    def withdraw(self, amount):
        if amount <= 0:
            raise NegativeAmountError("Amount must be positive")
        if amount > self.balance:
            raise InsufficientFundsError("Not enough money")
        self.balance -= amount

Common Built-in Exceptions

ExceptionWhen It Occurs
ValueErrorInvalid value for a function
TypeErrorWrong type for an operation
IndexErrorList index out of range
KeyErrorDict key not found
FileNotFoundErrorFile doesn’t exist
ZeroDivisionErrorDivision by zero
AttributeErrorObject has no attribute
ImportErrorImport failed
TimeoutErrorOperation timed out

Context Managers (with statement)

Automatically clean up resources:

# Instead of try/finally
with open("file.txt", "r") as file:
    content = file.read()
# File is automatically closed, even on exceptions

# Multiple resources
with open("input.txt") as infile, open("output.txt", "w") as outfile:
    outfile.write(infile.read())

EAFP vs LBYL

Python prefers EAFP (Easier to Ask Forgiveness than Permission):

# LBYL (Look Before You Leap) — Python doesn't prefer this
if key in data_dict:
    value = data_dict[key]
else:
    value = default

# EAFP — Pythonic way
try:
    value = data_dict[key]
except KeyError:
    value = default

Best Practices

# 1. Be specific with exceptions
try:
    result = database.query()
except DatabaseConnectionError:
    # Handle connection issue
except QueryError:
    # Handle query issue

# 2. Don't swallow exceptions silently
try:
    process_data()
except Exception:
    pass  # Bad! You'll never know something went wrong
    log.exception("Process failed")  # Good

# 3. Keep try blocks minimal
try:
    file = open("data.txt")
except FileNotFoundError:
    return
content = file.read()  # Not in the try block
file.close()

# 4. Log exceptions properly
import logging
try:
    risky_operation()
except Exception:
    logging.exception("Operation failed with error:")

Related: Learn Python list comprehensions and string methods.