Python - Exception Handling

9.
Discuss the role of the else block in exception handling.

Role of the else Block in Exception Handling:

In exception handling, the else block is used to specify a block of code that should be executed if no exceptions are raised in the try block. It provides a way to define code that should run only when the try block completes successfully, without any exceptions.

Here's an example program illustrating the role of the else block:

def divide_numbers(a, b):
    try:
        result = a / b

    except ZeroDivisionError:
        print("Cannot divide by zero!")

    else:
        print(f"The result of {a} divided by {b} is: {result}")

    finally:
        print("This code always runs, regardless of exceptions.")

# Example usage
divide_numbers(10, 2)
divide_numbers(10, 0)

Output (Example):

The result of 10 divided by 2 is: 5.0
Cannot divide by zero!
This code always runs, regardless of exceptions.

In this example, the divide_numbers function attempts to perform division in the try block. If a ZeroDivisionError occurs, the corresponding except block is executed. If no exception occurs, the else block is executed, printing the result. The finally block is always executed, providing a place for cleanup or finalization code.


10.
Explain the difference between the except Exception as e and except Exception, e syntax.

Difference Between except Exception as e and except Exception, e Syntax:

In Python, the except statement is used for catching and handling exceptions. There are two syntaxes for capturing exception information: except Exception as e and except Exception, e. Let's discuss the differences between them:

except Exception as e Syntax:

The as keyword is used to bind the exception instance to a variable (e in this case). This syntax is more modern and recommended in Python 2.6 and later versions. It allows you to access the exception instance and retrieve information about the exception, such as its message or attributes.

Here's an example program using except Exception as e:

try:
    # Some code that may raise an exception
    x = 10 / 0

except ZeroDivisionError as e:
    print(f"Caught an exception: {type(e).__name__}, Message: {e}")

except Exception, e Syntax:

This syntax is used in Python 2 and is considered outdated. It captures the exception instance and binds it to a variable (e). However, this syntax doesn't work in Python 3 and later versions, and it's not recommended for modern code.

Here's an example using the outdated except Exception, e syntax:

try:
    # Some code that may raise an exception
    x = 10 / 0

except ZeroDivisionError, e:
    print("Caught an exception:", type(e).__name__, ", Message:", e)

Note: In Python 3, the as syntax should be used, as shown in the first example.


11.
What is the purpose of the assert statement in exception handling?

The assert statement is used for debugging purposes in Python. It checks whether a given expression is True, and if it's not, it raises an AssertionError exception with an optional error message.

Here's an example program illustrating the use of the assert statement:

# Example program using assert statement
x = 10

# Check if x is positive
assert x > 0, "The value of x is not positive"

print("Assertion passed: x is positive")

In this example, the assert statement checks whether the value of x is positive. If the condition is False, it raises an AssertionError with the specified error message. If the condition is True, the program continues executing the next statement.

The output of the program (when the assertion passes) is:

Assertion passed: x is positive

If the assertion fails (e.g., if x is negative or zero), an AssertionError will be raised, and the program will terminate with an error message.


12.
How do you handle file-related exceptions in Python?

Handling file-related exceptions is crucial when working with file operations in Python. Common file-related exceptions include FileNotFoundError, PermissionError, and IOError. Below is an example program demonstrating how to handle file-related exceptions:

try:
    # Attempt to open a file for reading
    with open("nonexistent_file.txt", "r") as file:
        content = file.read()
        print(content)

except FileNotFoundError as e:
    print(f"Error: {e}. The specified file was not found.")

except PermissionError as e:
    print(f"Error: {e}. Permission denied to access the file.")

except IOError as e:
    print(f"Error: {e}. An I/O error occurred while reading the file.")

except Exception as e:
    print(f"An unexpected error occurred: {e}")

else:
    print("File read successfully.")

finally:
    print("File handling completed.")

In this example, the program attempts to open a file named "nonexistent_file.txt" for reading. Various exceptions are caught using specific except blocks, and a general except block is included to handle any other unexpected exceptions. The else block is executed if no exceptions occur, and the finally block is executed regardless of whether an exception occurred or not.

The output will be:

Error: [Errno 2] No such file or directory: 'nonexistent_file.txt'. The specified file was not found.
File handling completed.