Previous Index Next

What are exceptions?

An exception refers to an unexpected event or error that occurs during the execution of a program. When an exceptional situation arises, the program raises an exception to indicate that something has gone wrong. These exceptions disrupt the normal flow of the program.

Let's consider an example:

numbers = [1, 2, 3, 4, "5"]
total = sum(numbers)
average = total / len(numbers)
print("The average is:", average)

In this example, an exception occurs because we are attempting to perform addition on a numeric value and a string. An exception `TypeError` is raised during the sum operation.

When this exception occurs, the program stops and displays an error message like this:

Traceback (most recent call last):
File "example.py", line 2, in <module>
  total = sum(numbers)
TypeError: unsupported operand type(s) for +: 'int' and 'str'

In the above code snippet, a `TypeError` exception is raised during execution.

There are also other built-in exceptions available in Python. Now, let's explore built-in exceptions and understand when they are raised in more detail.

Built-in Exceptions

Built-in exceptions in Python are pre-defined classes that represent specific types of errors or exceptional situations that can occur during the execution of a program. These exceptions are part of the Python language and are designed to handle common error conditions.

ValueError:

The `ValueError` exception is raised when a function receives an argument of the correct type but with an inappropriate value.

It can occur when trying to convert a non-numeric string to an integer.

For example, if you try to convert the string "five" to an integer using the `int()` function, a `ValueError` will be raised.

ZeroDivisionError:

The `ZeroDivisionError` exception occurs when you try to divide a number by zero.

For example, if you try to divide the number 10 by 0, a `ZeroDivisionError` will be raised.

IndexError:

The `IndexError` exception is raised when you try to access an element from a list, tuple, or string using an invalid index. It occurs when you provide an index that is out of range or doesn't exist.

For example, if you try to access the 5th element of a list that has only 3 elements, an `IndexError` will be raised.

KeyError:

The `KeyError` exception is raised when you try to access a dictionary using a key that doesn't exist.

For example, if you try to access a non-existent key in a dictionary, a `KeyError` will be raised.

FileNotFoundError:

The `FileNotFoundError` exception is raised when an operation related to file handling fails because a file or directory cannot be found.

For example, if you try to open a file that doesn't exist, a `FileNotFoundError` will be raised.

NameError:

The `NameError` exception is raised when you attempt to use a variable that has not been defined in the current scope of your program. It serves as a reminder to check your code for any misspelled or undefined variables.

These are just a few examples of the built-in exceptions available in Python. By understanding these exceptions, you can identify the specific error that occurred and handle it appropriately in your code.

Handling Exceptions

Exception handling is a way to deal with errors in our code. It helps us prevent our program from abruptly stopping and allows us to respond to unexpected situations in a controlled manner. By handling exceptions, we can keep our program running smoothly, provide meaningful error messages, and fix issues more easily.

Exceptions in Python are handled using `try-except` blocks. The general syntax for handling exceptions is as follows:

try:
    # Code that may raise an exception
    ...
except SpecificException1:
    # Code to handle SpecificException1
    ...
except SpecificException2:
    # Code to handle SpecificException2
    ...
except:
    # Code to handle any other exception
    ...
else:
    # Code that executes if no exception is raised
    ...
finally:
    # Code always executes, whether an exception is raised or not
    ...

The `try` block contains the code that might raise an exception. If an exception occurs, it is caught by the appropriate `except` block. You can have multiple `except` blocks to handle different types of exceptions.

In the event that none of the specified exception types match the raised exception, we can include a generic `except` block without specifying any exception type. This block acts as a catch-all and handles any other exceptions that are not explicitly handled by the preceding `except` blocks. We can use this block to provide a general error handling mechanism.

The `else` block executes if no exception is raised, and the `finally` block always runs, providing a place for cleanup code. Exception handling ensures that your program can recover from errors and continue its execution smoothly.

Example 1: using `try-except`

The following example demonstrates the usage of a simple `try-except` block without specifying the exception type. It catches any exception that occurs and displays a generic error message.

try:
    num1 = int(input("Enter the first number: "))
    num2 = int(input("Enter the second number: "))

    result = num1 / num2
    print("The division result is:", result)

except:
    print("An error occurred during execution.")

If any error occurs during the execution of the code inside the `try` block, the program jumps to the `except` block. The `except` block catches the error and displays a generic error message: "An error occurred during execution."

Example 2: using `try-except` with specific exception handlers

The following example shows the usage of specific exception handlers to provide customized error messages based on the specific exception type.

try:
    num1 = int(input("Enter the first number: "))
    num2 = int(input("Enter the second number: "))

    result = num1 / num2
    print("The division result is:", result)

except ValueError:
    print("Invalid input. Please enter valid integers.")

except ZeroDivisionError:
    print("Error: Division by zero is not allowed.")

except:
    print("An error occurred during execution.")

If an error occurs during the execution of the code inside the `try` block, the program jumps to the `except` block that matches the type of error.

In this example, we have three different `except` blocks:

  • The first `except` block, `ValueError`, handles the situation when the user enters something that cannot be converted to an integer. It displays a message saying "Invalid input. Please enter valid integers."
  • The second `except` block, `ZeroDivisionError`, handles the situation when the user enters 0 as the second number, which leads to division by zero. It displays a message saying "Error: Division by zero is not allowed."
  • The third `except` block, which doesn't specify a particular error type, acts as a catch-all for any other unexpected errors. It displays a message saying "An error occurred during execution."

Example 3: Using `try-except-else`

If you only need to handle exceptions and display custom error messages, Example 2 approach is sufficient. However, if you have additional actions or operations to perform when no exceptions occur, `try-except-else` provides a more structured approach.

try:
    num1 = int(input("Enter the first number: "))
    num2 = int(input("Enter the second number: "))

    result = num1 / num2

except ValueError:
    print("Invalid input. Please enter valid integers.")

except ZeroDivisionError:
    print("Error: Division by zero is not allowed.")

except:
    print("An error occurred during execution.")

else:
    print("The division result is:", result)

Example 4: `finally` in exception

The following example demonstrates the usage of the `finally` block for resource cleanup. In this case, the file is opened in the `try` block, and regardless of whether an exception occurs or not, the `finally` block ensures that the file is closed.

try:
    file = open("example.txt", "r")
    content = file.read()
    print(content)

except FileNotFoundError:
    print("Error: File not found.")

finally:
    if file:
        file.close()
        print("File closed.")
      

This program attempts to open a file called "example.txt" and read its content. If the file is not found, it displays an error message. Regardless of any error, the file is closed using the `finally` block. The `try-except-finally` structure allows us to handle errors gracefully and ensure proper file handling.

Raising an Exception

Exceptions are raised automatically by the Python interpreter when it encounters an error condition during the execution of code. For example, if you try to divide a number by zero, the interpreter will raise exceptions like `ZeroDivisionError`. This exception is raised without any explicit code on our part.

Sometimes, we may need to raise exceptions ourselves to indicate that something erroneous has occurred in our code. The `raise` keyword is used in Python to explicitly raise an exception. For example, in the following example code, we use the `raise` keyword to explicitly raise a `ValueError` exception if the entered salary is negative.

# Prompt the user to enter salary
salary = input("Enter your salary: ")

try:
    # Convert the user's input to a floating-point number
    salary = float(salary)
    
    # Check if the salary is valid
    if salary < 0:
        raise ValueError("Salary cannot be negative.")
  
    # If the salary is valid, print it
    print("Your salary is:", salary)
    
except ValueError as e:
    print("Invalid input:", str(e))

In this example, we prompt the user to enter their salary. We convert the input to a floating-point number and check if it is negative. If the salary is negative, we explicitly raise a 'ValueError' exception with a custom error message: "Salary cannot be negative."

The 'except' block then catches the 'ValueError' exception and displays the custom error message. Raising exceptions allows us to handle specific error conditions in our code and provide meaningful feedback to the user.

Conclusion

Exception handling is an essential aspect of programming in Python. By understanding exceptions, their types, and how to handle them, you can write more robust and reliable code. Proper exception handling ensures that your program gracefully handles unexpected situations, provides meaningful error messages, and allows for appropriate recovery or termination of the program.

Previous Index Next