Exception Handling

Unexpected situations always occur during program execution — files don't exist, network disconnects, users enter invalid data... Without handling these "exceptions," the program crashes. Exception handling allows your program to recover from errors and provide user-friendly prompts instead of cryptic error messages.


1. What is an Exception

An exception is an error that occurs during program execution. If an exception is not handled, the program terminates:

PYTHON
# This code will crash
# print(10 / 0)               # ZeroDivisionError: division by zero
# int("abc")                  # ValueError: invalid literal for int()
# open("non_existent.txt")    # FileNotFoundError

Use try-except to handle these errors gracefully:

Example: try-except Handling Division and Input Errors

PYTHON
try:
    number = int(input("Enter a number: "))
    result = 10 / number
    print(f"10 / {number} = {result}")
except ValueError:
    print("That's not a valid number!")
except ZeroDivisionError:
    print("Cannot divide by zero!")
▶ Try it Yourself

Sample run:

TEXT
Enter a number: abc
That's not a valid number!

Tip: Exception handling philosophy: Instead of using try to "predict all possible errors," it's about "doing things first and dealing with problems when they arise." The Python community calls it: "It's easier to ask for forgiveness than permission" (EAFP).


2. Complete try-except Structure

Example: try-except-else-finally Full Structure

PYTHON
try:
    # Code that might error
    file = open("data.txt", "r", encoding="utf-8")
    content = file.read()
    number = int(content)
    print(f"The number is: {number}")
except FileNotFoundError:
    print("File not found!")
except ValueError:
    print("File content is not a valid number!")
else:
    # Executes when no exception occurs
    print("Successfully read and converted!")
finally:
    # Always executes, regardless of exceptions
    print("Cleanup: closing file")
    try:
        file.close()
    except NameError:
        pass
▶ Try it Yourself
Part When it executes Purpose
try Always Put potentially error-prone code here
except When the specified exception occurs Handle the error
else When no exception occurs Logic after success
finally Always (with or without exception) Clean up resources (close files/release connections)

Tip: In real development, else is used less frequently, while finally is used extensively. The with statement (context manager) handles resource release automatically and can often replace finally.


3. Common Exception Types

PYTHON
# ZeroDivisionError — division by zero
# int("abc")                # ValueError — invalid value
# [1, 2][5]                 # IndexError — index out of range
# {"a": 1}["b"]             # KeyError — key doesn't exist
# open("x.txt")             # FileNotFoundError — file not found
# 10 + "hello"              # TypeError — type error
# import nonexistent        # ModuleNotFoundError — module not found

Example: Correct vs Wrong Way to Catch Exceptions

PYTHON
try:
    # Some code
    pass
except:                     # Catches ALL exceptions
    print("Something went wrong")

try:
    pass
except Exception as e:      # Catches known exceptions
    print(f"Error: {e}")
▶ Try it Yourself

Warning: Bare except: is not recommended — it catches system exceptions like KeyboardInterrupt (Ctrl+C) and SystemExit, preventing normal program termination. Use except Exception as e instead. Best practice is to only catch the specific exception types you expect.


4. raise: Raising Exceptions Explicitly

Sometimes you need to tell the caller "something went wrong." Use raise:

Example: raise to Raise an Exception

PYTHON
def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero!")
    return a / b

try:
    result = divide(10, 0)
except ValueError as e:
    print(f"Error: {e}")     # Error: Cannot divide by zero!
▶ Try it Yourself

Password Strength Check Example

Example: raise for Password Validation

PYTHON
def validate_password(password):
    """Validate password strength; raise exception if conditions aren't met"""
    if len(password) < 6:
        raise ValueError("Password must be at least 6 characters")
    if not any(c.isdigit() for c in password):
        raise ValueError("Password must contain a digit")
    if not any(c.isalpha() for c in password):
        raise ValueError("Password must contain a letter")
    return True

try:
    validate_password("123")
except ValueError as e:
    print(f"Invalid password: {e}")
▶ Try it Yourself

Tip: When to use raise? When a function encounters a situation that "shouldn't happen" — invalid parameter values, unsatisfied preconditions, unavailable dependencies. Raise an exception to let the caller decide how to handle it, rather than silently swallowing the error inside the function.


5. Custom Exception Classes

You can create your own exception types for more precise error information:

Example: Custom Exceptions for Bank Withdrawal

PYTHON
class BalanceError(Exception):
    """Insufficient balance exception"""
    pass

class AccountLockedError(Exception):
    """Account locked exception"""
    pass

def withdraw(balance, amount):
    if amount > balance:
        raise BalanceError(f"Insufficient balance! Need {amount}, have {balance}")
    if balance < 0:
        raise AccountLockedError("Account is locked")
    return balance - amount

try:
    withdraw(100, 200)
except BalanceError as e:
    print(f"Transaction failed: {e}")
except AccountLockedError as e:
    print(f"Transaction failed: {e}")
▶ Try it Yourself

Tip: Custom exceptions make your code clearer — callers can precisely handle different types of errors. Simply inherit from Exception; usually just a class name is sufficient, no extra methods needed.


6. logging: Professional Error Logging

Using print() for error messages works in simple scripts, but in production projects, use the logging module:

Example: logging Configuration and Usage

PYTHON
import logging

# Basic configuration
logging.basicConfig(
    level=logging.INFO,          # Log level
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler("app.log", encoding="utf-8"),  # Write to file
        logging.StreamHandler()                            # Also output to console
    ]
)

# Different log levels
logging.debug("Debug info")        # Debugging, usually not output
logging.info("Application started successfully")     # General info
logging.warning("Disk usage at 85%")  # Warning
logging.error("Database connection failed")   # Error
logging.critical("System crash!")    # Fatal error
▶ Try it Yourself

Output (written to both file and console):

TEXT
2026-06-23 16:00:00,123 [INFO] Application started successfully
2026-06-23 16:00:00,124 [WARNING] Disk usage at 85%
2026-06-23 16:00:00,124 [ERROR] Database connection failed

Tip: Benefits of logging over print(): 1) Can output to both console and file simultaneously. 2) Has level control (show all during development, only WARNING+ in production). 3) Auto-includes timestamps. 4) No need to delete a bunch of print() statements before release.


Common Use Cases


FAQ

Q What does as e mean in except Exception as e?
A as e assigns the caught exception object to the variable e, allowing you to inspect the exception details — print(e) shows the error description, type(e).__name__ shows the exception type name. Without as e, you can still catch the exception but can't see detailed error information.
Q When should I use exceptions vs. if checks?
A Use if for errors you can predict in advance (like checking for zero divisor). Use try-except for errors you can't predict (like network requests, file operations). The Python community's EAFP style leans toward using try — but this is a matter of aesthetics, and both approaches have their use cases.
Q Does code in finally always execute?
A Almost always — even if the try block has return, break, or continue, finally still executes. The only exception is when the program is forcibly terminated (e.g., os._exit() or a power outage). This makes finally an excellent place for resource cleanup.

Summary


Exercises

  1. Beginner (Difficulty: Star): Write a program that asks the user for two numbers and computes their division. Use try-except to handle ValueError (input is not a number) and ZeroDivisionError (division by zero), each with a friendly error message.

  2. Intermediate (Difficulty: Star-Star): Write a function read_int_from_file(filename) that reads the first number from a file and returns it. Use try-except to handle: file not found, file content is not a valid number, file is empty. Return a different error message for each case.

  3. Advanced (Difficulty: Star-Star-Star): Write a "safe calculator" program. The user enters an expression (e.g., 10 / 3), and the program computes and outputs the result. Requirements: 1) Use try-except to handle division by zero, value errors, and type errors. 2) Use logging to record each calculation operation (INFO) and error (ERROR) to a calculator.log file. 3) Support exit to quit. Hint: Use eval() to evaluate the expression (note security concerns — acceptable for this exercise).

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏