🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

Mastering Python Exception Handling (try-except)

To run Python from the command prompt or PowerShell on your PC, you need to download and install Python.
If you haven’t installed it yet, please refer to the article Setting Up Python and Development Environment to install Python.

When writing programs, encountering unexpected errors is inevitable. The causes of errors are varied, such as incorrect user input, non-existent files, or network issues. "Exception handling" is the mechanism that prevents your program from suddenly crashing and allows you to respond intelligently.

In this article, we'll explain the basics and applications of exception handling using Python's try-except statement in a way that's easy for beginners to understand, complete with code examples you can copy and paste to run immediately. Let's master how to build robust, error-resistant programs by experiencing "working" code firsthand!


The Basics First! The try-except Syntax

The most fundamental form of exception handling is the try-except statement. As the name suggests, it creates a flow: "try this, and if an exception (error) occurs, except (catch and handle) it."

The syntax is very simple.

  1. Inside the try block, you write the code that might cause an error.
  2. Inside the except block, you write the code you want to execute when an error occurs.

Seeing is believing. Let's look at the famous "ZeroDivisionError" as an example. The code below attempts to divide 10 by 0. Normally, this would crash the program with an error, but with try-except, we can catch it properly.


<!-- Python Code -->
try:
  # Code that might cause an error
  result = 10 / 0
  print(f"Calculation result: {result}")
except ZeroDivisionError:
  # Action to take if a ZeroDivisionError occurs
  print("Oops! You can't divide by zero.")

print("The program finished normally.")
    

Targeting Specific Exceptions! Multiple excepts

In programming, various types of errors can occur. For example, with user input, you might get a "ValueError" (when a string is entered instead of a number), or with file operations, a "FileNotFoundError" (when the specified file doesn't exist).

By specifying the type of error (the exception class) after the except statement, you can catch only specific errors and perform appropriate actions for each.

Furthermore, by lining up multiple except blocks, you can write different handlers for different types of errors. The following example tries to convert a string to an integer.


<!-- Python Code -->
user_input = "hello" # A string, not a number

try:
  num = int(user_input)
  print(f"Entered number: {num}")
except ValueError:
  print("Please enter a number! A string cannot be converted to a number.")
except TypeError:
  print("Type mismatch! The type is not convertible to a number.")

print("Continuing processing...")
    

You'll often want to know the detailed information (error message) of an error that occurred. In that case, you can use as to store the exception object in a variable. The variable name e (initial for error or exception) is commonly used.


<!-- Python Code -->
try:
  # Attempt to open a non-existent file
  with open("non_existent_file.txt", "r") as f:
    content = f.read()
except FileNotFoundError as e:
  # Display detailed error information
  print(f"File not found.")
  print(f"Error details: {e}")

    

Advanced Usage: Mastering else and finally

The try-except statement has two powerful companions: else and finally. Combining them allows for more fine-grained control.

Let's look at some code that uses all these elements.


<!-- Python Code -->
file_path = "my_data.txt"
data_to_write = "This is test data."

try:
  print(f"Writing data to '{file_path}'...")
  f = open(file_path, "w", encoding="utf-8")
  # To intentionally cause an error, uncomment the next line
  # f.write(12345) # TypeError occurs if trying to write non-string data
  f.write(data_to_write)
  print("Attempted to write.")

except TypeError as e:
  print(f"Error! Data to write must be a string.")
  print(f"Error details: {e}")

except Exception as e:
  # Catch any other unexpected errors
  print(f"An unexpected error occurred.")
  print(f"Error details: {e}")

else:
  # Executes if no exception occurred in the try block
  print("Successfully wrote to the file!")

finally:
  # Always executes, regardless of exceptions
  if 'f' in locals() and not f.closed:
    f.close()
    print("File has been closed.")
  else:
    print("File was not open or was already closed.")

print("--- Processing Complete ---")
    

Hands-On! A Complete, Runnable Code Example

Now, let's use everything we've learned to create a more practical program. This code asks the user for their age and repeatedly prompts them until a valid number is entered. It then saves the entered age to a file. Potential errors along the way are handled by try-except.

Copy the entire code below, save it as a file named age_logger.py, and run it in your terminal with python age_logger.py. Try intentionally entering text to see how the error handling works!


<!-- Full Python Script: age_logger.py -->
import datetime

def record_age():
    """
    A function to ask for the user's age and record it to a file.
    Handles input validation and file I/O errors.
    """
    while True:
        try:
            # Receive input from the user
            age_str = input("Please enter your age as a number: ")

            # Convert the string to an integer
            age = int(age_str)

            # Check for negative values or unrealistic ages
            if age < 0 or age > 130:
                # Raise a custom error
                raise ValueError("Age must be between 0 and 130.")

            # If a valid age is entered, break the loop
            break

        except ValueError as e:
            # Catch ValueError from int() conversion or the raised one
            print(f"Error: {e}")
            print("Please try again with a valid number.\n")

    # Record to file
    try:
        # The with statement automatically closes the file, so a finally block for close() is not needed
        with open("age_log.txt", "a", encoding="utf-8") as f:
            timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            f.write(f"[{timestamp}] Recorded Age: {age}\n")
        
        print(f"Your age, '{age}', has been recorded to 'age_log.txt'.")

    except IOError as e:
        # Catch errors like lack of file write permissions
        print("Fatal Error: Failed to write to the file.")
        print(f"Error details: {e}")

if __name__ == "__main__":
    record_age()
    print("Thank you for using the program.")

    

Points to Watch Out For: Catching Broad Exceptions

Exception handling is useful, but misusing it can make it harder to find problems in your program. A particular point of caution is catching exceptions that are too broad.

Not Recommended: Bare except

The worst practice is a "bare except:" that doesn't specify an exception class. This indiscriminately catches all errors. This includes SystemExit, which is used to terminate the program, and even KeyboardInterrupt from pressing Ctrl+C. You could end up in a situation where you can't even stop your program when you want to.

Use with Caution: except Exception

except Exception as e: is better than a bare except:, but it still catches most common errors. During development, you often want errors to occur to find unexpected bugs. If you catch everything, bugs that should be fixed can be hidden.

The best practice is to "specify and catch only those exceptions that you can predict and handle appropriately."


Summary and Next Steps

In this article, we learned about Python's try-except statement for exception handling. Let's review the key points.

  • You can prevent program crashes due to errors with try-except.
  • With except ExceptionClass as e, you can catch specific errors and get detailed information.
  • Use else for success cases and finally for cleanup operations.
  • The trick is to narrow down exception catching to specific, handleable cases rather than being too broad.

By mastering exception handling, you can build robust applications that are user-friendly and easy for developers to maintain. Be sure to introduce try-except into your own code.

As a next step, why not learn about an important concept for modularizing your program and increasing its reusability?

>> Next Article: Introduction to Python Classes and Object-Oriented Programming