Latest posts

10/recent/ticker-posts

Exception Handling in Python Programming | Mastering Exception Handling in Python: Building Robust and Reliable Code | try-catch in Python | try block in Python


Hey everyone, in the last post on Python we have seen Break and Continue statements of Python Programming. Now we are going to learn something new, which is Exception Handling in Python Programming.

Exception handling is an essential aspect of Python programming that allows developers to gracefully handle errors and exceptions that may occur during the execution of their code. By employing robust exception-handling techniques, programmers can ensure that their programs continue to run smoothly even in the face of unexpected issues. 

Sometimes due to improper knowledge of any block of code, unsureness of any output, or any other reason, the errors occur during the execution of the programs. So to handle this type of error we use exceptions to handle it.

In this blog post, we will explore the importance of exception handling and delve into various strategies and best practices for effectively managing exceptions in Python.

What is an Exception?

In Python, an exception is an event that occurs during the execution of a program, which disrupts the normal flow of the program. It represents an error or an exceptional condition that needs to be handled by the program. When an exception occurs, Python generates an exception object that contains information about the error, such as the type of exception and a traceback that shows the sequence of function calls leading to the exception.

Exceptions can occur due to various reasons, including but not limited to:

  1. Invalid input: When the program receives unexpected or incorrect input, such as trying to convert a non-numeric string to an integer.
  2. Division by zero: Attempting to divide a number by zero will result in a ZeroDivisionError. File not found: If a program tries to open a file that does not exist, a FileNotFoundError will be raised.
  3. Network errors: When working with network operations, exceptions can occur due to issues such as a connection timeout or a server not responding.
Python provides a wide range of built-in exception types, such as ValueError, TypeError, IndexError, and FileNotFoundError, among others. These exceptions have specific meanings and are designed to handle different types of errors. Additionally, developers can create custom exceptions by subclassing existing exception types or the built-in Exception class, allowing them to handle application-specific exceptional conditions.

By utilizing exception-handling techniques, developers can catch and handle exceptions, allowing the program to gracefully recover from errors, provide appropriate error messages, or perform necessary cleanup operations. Exception handling helps improve the robustness and reliability of programs by preventing unexpected errors from crashing the program and enabling controlled error handling and recovery.

How to handle runtime exceptions :

In Python, to handle the runtime errors or exceptions, and to continue the flow of program execution we use the Try-except block.

The fundamental construct for exception handling in Python is the try-except block. The code enclosed within the try block is executed, and if an exception occurs, it is caught and handled within the except block. By utilizing multiple except blocks, developers can specify different exception types and define custom handling mechanisms for each case. This allows for fine-grained control over error handling and enables tailored responses based on the specific exception type.

It means, if you are not sure about our code is working properly or not, or don't know what the output is actually, then it's a better practice to use a try-except block.

How to use try-except block :

In Python programming, we use the try-except block to handle exceptions.
So here is a basic syntax of the try-except block of Python.

Syntax : 
try:
    # Code that may raise an exception
    # ...
except ExceptionType1:
    # Code to handle the exception of type ExceptionType1
    # ...
except ExceptionType2:
    # Code to handle the exception of type ExceptionType2
    # ...
except:
    # Code to handle any other exceptions
    # ...
finally:
    # Optional: Code that runs regardless of whether an exception occurred or not
    # ...

So this is a basic syntax of the try-except block. In that, we used a try block to write the code, which is not sure of properly working or which may create some errors during execution.

After that, we are able to use a number of except blocks to handle the multiple exceptions.

Example 1 : 
try:
    num1 = int(input("\nEnter 1st Number : "))
    num2 = int(input("Enter 2nd Number : "))

    print(f"\nAddition : {num1 + num2}")
    print(f"Subtraction : {num1 - num2}")
    print(f"Multiplication : {num1 * num2}")
    print(f"Division : {num1 / num2}\n")
    
except ZeroDivisionError:
    print("\nError: Division by zero is not allowed !\n")
    
except IOError:
    print(Exception)


So in this example, we have used a try block to do some of the calculations. After the try block, we used three except blocks to handle Exceptions.

In the first except block, we throw an exception ZeroDivisionError to handle the error. because,  when the user tries to divide a number with 0, then the division is not possible, so at the time of execution the compiler will break the execution flow.
To avoid this problem, we used the exception ZeroDivisionError.

Because of this exception, the program flow will doesn't stop.

In the second except block, we have used an Exception called IOError.
This exception will handle the Input Output Errors while execution of the program.

Example 2 :
try:
    num1 = int(input("\nEnter 1st Number : "))
    num2 = int(input("Enter 2nd Number : "))

    print(f"\nAddition : {num1 + num2}")
    print(f"Subtraction : {num1 - num2}")
    print(f"Multiplication : {num1 * num2}")
    print(f"Division : {num1 / num2}\n")
    
except ZeroDivisionError:
    print("\nError: Division by zero is not allowed !\n")
    
except ImportError:
    print("\nError : Entered invalid Values !\n")
    
except IOError:
    print(Exception+"\n")

else:
    print("Calculation Done !\n")

print("Execution Successful ! \n")


In this example, we have used one more statement with a try-except block, that is else statement. The else statement is used to show the final output of the code when the code doesn't get any errors.

In this construct, the code within the try block is executed. If an exception is raised during the execution of the try block, the corresponding except block is executed to handle the exception. You can have multiple except blocks to handle different exception types selectively. 

If no exceptions occur within the try block, the code within the else block is executed. This section allows you to specify code that should run only when no exceptions were raised. It provides a way to separate the "normal" execution flow from the exceptional cases.

Syntax : 
try:
    # Code that may raise an exception
    # ...
except ExceptionType1:
    # Code to handle the exception of type ExceptionType1
    # ...
except ExceptionType2:
    # Code to handle the exception of type ExceptionType2
    # ...
else:
    # Code that runs if no exceptions occur
    # ...

The finally block of exception handling : 

The finally block is an optional part of the exception-handling mechanism. It is used to define a block of code that will be executed regardless of whether an exception occurs or not. The finally block ensures that certain actions or cleanup operations are performed, providing a way to guarantee the execution of specific code paths.

Syntax :
try:
    # Code that may raise an exception
    # ...
except ExceptionType1:
    # Code to handle the exception of type ExceptionType1
    # ...
except ExceptionType2:
    # Code to handle the exception of type ExceptionType2
    # ...
finally:
    # Code that will always execute, regardless of exceptions
    # ...

The try block contains the code that may raise exceptions. If an exception occurs, the corresponding except block that matches the exception type is executed to handle the exception. Multiple except blocks can be used to handle different exception types.

The finally block comes after the try-except blocks and is executed regardless of whether an exception occurs or not. It provides a place to include cleanup code or actions that must be performed, such as closing files, releasing resources, or resetting variables.

Example :
try:
    file = open("data.txt", "r")
    # Perform operations on the file
    # ...
except FileNotFoundError:
    print("Error: File not found.")
finally:
    if file:
        file.close()
    print("Cleanup complete.")


Good practices to use Exception Handling : 

A. Be specific: Catch only the exceptions you expect and can handle. Avoid using a bare except block, as it can mask errors and make debugging challenging.

B. Use multiple except blocks: Different exceptions require different handling strategies. By catching specific exceptions individually, you can provide context-specific error handling and maintain code clarity.

C. The else clause: The else clause in a try-except block is executed if no exceptions are raised. It allows you to specify code that should run only when no exceptions occur, enabling you to separate the exceptional and non-exceptional cases cleanly.

D. The finally block: The finally block is executed regardless of whether an exception occurs or not. It is typically used to release resources, close files, or perform any necessary cleanup operations.

Raising Manual Exceptions :

Python allows developers to manually raise exceptions using the raise statement. This is useful when you want to explicitly signal an exceptional condition within your code. By raising custom exceptions, you can communicate specific error scenarios and ensure appropriate handling at higher levels of the program.

Raising a manual exception involves explicitly signaling that an exceptional condition has occurred at a certain point in your code. This can be done using the raise statement followed by an instance of an exception class.

To raise a manual exception, you generally follow these steps:

Step 1 : Define a custom exception class: You need to define a new class that inherits from the built-in Exception class or one of its subclasses. This class will represent your custom exception and can include additional attributes or methods if needed.

Example : 
class MyException(Exception):
    pass

Step 2 : Raise the exception: At the appropriate point in your code, you can raise an instance of your custom exception class using the raise statement. You can also provide an optional error message that describes the reason for the exception.

Example : 
raise MyException("This is an Manual Exception !")

Stepe 3 :  Handling the exception: Once the exception is raised, the program flow will be interrupted, and Python will start searching for an exception handler that can handle the raised exception. You can use a try-except block to catch and handle the exception.

Example : 
class MyException(Exception):
    pass

try:
    raise MyException("This is an Manually created Exception !")

except MyException as e:
    print(f"\nException : {e}")

print("\nExecution Successful ! \n")



Exception Handling and Tracebacks:

When an exception occurs, Python provides a traceback—a detailed report that shows the sequence of function calls leading up to the exception. Understanding traceback information can be immensely helpful for identifying the root cause of an error and debugging code effectively. Python's traceback module offers additional functionality for working with tracebacks programmatically.

Exception Handling Beyond Basics :

A. Exception chaining: Python 3 introduced the ability to chain exceptions using the raise statement, preserving the original exception's traceback while wrapping it in a higher-level exception.

B. Custom exception classes: By creating custom exception classes, you can define your application-specific exceptions, providing better clarity and organization in your code.

Conclusion:

Exception handling is an indispensable skill for any Python developer. By understanding the nuances of exception handling and following best practices, you can write more robust and resilient code. Python's exception-handling mechanisms offer flexibility and control, allowing you to gracefully handle errors and guide your program's execution flow even in the face of unexpected issues. Embrace the art of exception handling, and elevate your Python programming skills to new heights. Happy coding!


We hope it will help you to be a Perfect Programmer...!

Thank You !




Also Visit


Post a Comment

0 Comments