Overview:
Exception handling is a critical aspect of writing robust and error-tolerant Python code. This lesson introduces the fundamental concepts of exception handling, exploring how to anticipate and gracefully manage errors that may arise during program execution. Whether dealing with input, file operations, or complex algorithms, understanding how to handle exceptions is key to creating reliable and maintainable Python applications.
In Python, the try and except blocks are used for error handling. The basic idea is to enclose the code that might raise an exception inside a try block, and then specify the actions to be taken if an exception occurs in an associated except block.
Here is a simple example:
try: # Code that might raise an exception x = int(input("Enter a number: ")) result = 10 / x print("Result:", result) except ZeroDivisionError: print("Cannot divide by zero!") except ValueError: print("Invalid input. Please enter a valid number.") except Exception as e: print("An unexpected error occurred:", e) else: print("No exception occurred.") finally: print("This block always executes.")
In this example:
You can customize the except blocks based on the specific exceptions you anticipate in your code. It’s a good practice to catch specific exceptions rather than using a broad except block that catches all exceptions, as this allows you to handle different exceptions in different ways.
Try-Except Block:
try: # Code that may raise an exception result = 10 / 0 # This will raise a ZeroDivisionError except ZeroDivisionError: # Handle the specific exception print("Cannot divide by zero!") except Exception as e: # Handle other types of exceptions print("An error occurred:", e) else: # Optional block executed if no exception occurs print("No exception occurred.") finally: # Optional block always executed, whether an exception occurred or not print("This block always executes.")
You can handle multiple exceptions in a single except block or have separate except blocks for each exception type.
try: # Code that may raise an exception value = int("abc") # This will raise a ValueError except (ZeroDivisionError, ValueError) as e: # Handle multiple exception types print(f"An error occurred: {e}") ### Custom Exceptions: You can also define and raise your own custom exceptions to handle specific scenarios. ```python class CustomError(Exception): def __init__(self, message): self.message = message try: raise CustomError("This is a custom exception") except CustomError as ce: print(f"Custom exception caught: {ce.message}")
Handling multiple exceptions in Python can be done using multiple except blocks, one for each type of exception you want to handle.
Here’s an example:
try: # Code that may raise an exception num1 = int(input("Enter the first number: ")) num2 = int(input("Enter the second number: ")) result = num1 / num2 except ValueError: # Handle a ValueError (e.g., when the enters a non-integer) print("Invalid input. Please enter a valid number.") except ZeroDivisionError: # Handle a ZeroDivisionError (e.g., when the enters 0 as the second number) print("Cannot divide by zero!") except Exception as e: # Handle other types of exceptions print(f"An unexpected error occurred: {e}") else: # Executed if no exception occurs print("Result:", result) finally: # Always executed, for cleanup or finalization print("This block always executes.")
In this example:
If you want to handle multiple exceptions in the same way, you can combine them in a single except block:
try: # Code that may raise an exception num1 = int(input("Enter the first number: ")) num2 = int(input("Enter the second number: ")) result = num1 / num2 except (ValueError, ZeroDivisionError) as e: # Handle both ValueError and ZeroDivisionError print(f"An error occurred: {e}") except Exception as e: # Handle other types of exceptions print(f"An unexpected error occurred: {e}") else: # Executed if no exception occurs print("Result:", result) finally: # Always executed, for cleanup or finalization print("This block always executes.")
In this case, both ValueError and ZeroDivisionError are caught in the same except block.
The else block in a try-except structure is executed only if no exceptions occur in the preceding try block. It provides a way to specify a block of code that should run when the code in the try block executes successfully without raising any exceptions.
Here’s the basic structure:
try: # Code that may raise an exception result = operation_that_might_fail() except SomeSpecificException: # Handle a specific exception handle_specific_exception() except AnotherSpecificException: # Handle another specific exception handle_another_specific_exception() else: # This block is executed if no exceptions occur in the try block print("Operation successful!") print("Result:", result) finally: # This block always executes, regardless of whether an exception occurred or not cleanup_operations()
In this example:
Here’s a simple example:
try: x = int(input("Enter a number: ")) result = 10 / x except ValueError: print("Invalid input. Please enter a valid number.") except ZeroDivisionError: print("Cannot divide by zero.") else: print("Division successful!") print("Result:", result) finally: print("This block always executes.")
Here’s the basic structure:
try: # Code that may raise an exception result = operation_that_might_fail() except SomeSpecificException: # Handle a specific exception handle_specific_exception() except AnotherSpecificException: # Handle another specific exception handle_another_specific_exception() else: # This block is executed if no exceptions occur in the try block print("Operation successful!") print("Result:", result) finally: # This block always executes, regardless of whether an exception occurred or not cleanup_operations()
In this example:
This is where you put cleanup operations.
Here’s a simple example:
try: x = int(input("Enter a number: ")) result = 10 / x except ValueError: print("Invalid input. Please enter a valid number.") except ZeroDivisionError: print("Cannot divide by zero.") else: print("Division successful!") print("Result:", result) finally: print("This block always executes.") # Additional cleanup operations can be performed here
Here’s a simple example of how to use the raise statement:
def divide_numbers(x, y): if y == 0: raise ValueError("Cannot divide by zero") return x / y try: result = divide_numbers(10, 0) except ValueError as ve: print(f"Error: {ve}") else: print("Result:", result)
In this example:
You can create and raise custom exceptions by defining your own exception class, typically inheriting from the Exception class.
Here’s an example:
class MyCustomError(Exception): pass def example_function(): # Some code raise MyCustomError("This is a custom exception") try: example_function() except MyCustomError as ce: print(f"Custom exception caught: {ce}")
a. To handle specific exceptions
b. To define cleanup operations
c. To enclose code that might raise an exception
d. To always execute a block of code
a. finally
b. else
c. except
d. None of the above
a. Use multiple except blocks
b. Use a tuple of exception types in a single except block
c. Combine except and else blocks
d. Use a try block inside another try block
a. Code that may raise an exception
b. Handling specific exceptions
c. Cleanup operations
d. Code that runs if no exceptions occur
a. Using the break statement
b. Using the throw statement
c. Using the raise statement
d. Using the except statement
a. They are faster than built-in exceptions
b. They make the code shorter and more concise
c. They provide more information about the exceptional condition
d. They are required for proper error handling
a. To handle specific exceptions
b. To define cleanup operations
c. To execute code if no exceptions occur in the try block
d. To always execute a block of code
a. It handles specific exceptions
b. It provides more information about the error
c. It always executes, regardless of exceptions
d. It makes the code more readable
Answers:
1-c
2-b
3-b
4-c
5-c
6-c
7-c
8-c
a. To always execute a block of code
b. To define cleanup operations
c. To enclose code that might raise an exception
d. To handle specific types of exceptions
a. Using the get_error_message() function
b. Accessing the error attribute of the exception object
c. Using the message keyword in the except block
d. Accessing the args attribute of the exception object
a. The order of except blocks doesn’t matter
b. The first matching except block is executed, and others are ignored
c. The last matching except block is executed, and others are ignored
d. except blocks are executed in random order
a. To handle exceptions
b. To raise an exception if a condition is False
c. To define custom exceptions
d. To suppress exceptions
a. Always, as it simplifies the code
b. Only in small scripts or quick prototypes
c. Never, it’s considered bad practice
d. When dealing with input
a. Yes, you can have both else and finally blocks
b. No, it’s not allowed to have both else and finally blocks
c. Yes, but only in specific situations
d. No, you can have either else or finally, but not both
a. To create a new file
b. To open a file for reading or writing
c. To handle exceptions related to file operations
d. To automatically close files after their suite finishes execution
Answers:
9. d
10-d
11-b
12-b
13-c
14-a
15-d