PCAP - Python Certification Course
Exceptions
Hierarchy of Exceptions
Python 3 provides 63 built-in exceptions that are organized in a hierarchical tree. For example, a ZeroDivisionError is a specialized exception under ArithmeticError, which in turn is a subtype of Exception. Ultimately, all these derive from BaseException.
Because ZeroDivisionError inherits from ArithmeticError, you can design your exception handling logic to catch any ArithmeticError, not just a ZeroDivisionError. However, ensure that your error messages are generic enough because the caught error might not strictly be about division by zero. Additionally, if you specify multiple exception handlers (for instance, both ZeroDivisionError and ArithmeticError), only the first matching branch will execute. This makes the order of exception handlers critical for accurate error handling.
Below is a sample code snippet illustrating these concepts:
try:
x = int(input("Enter a number: "))
y = 1 / x
print(y)
except ZeroDivisionError:
print("You cannot divide by zero.")
except ArithmeticError:
print("Calculation failed.")
except:
print("Something else went wrong")
print("All done!")
Example output when the input is 0:
Enter a number:
0
You cannot divide by zero.
All done!
If you want to handle two or more exceptions in the same way, you can combine them into a tuple. Consider the following example:
try:
x = int(input("Enter a number: "))
y = 1 / x
print(y)
except (ZeroDivisionError, ValueError):
print("Invalid input value")
except ArithmeticError:
print("Calculation failed.")
except:
print("Something else went wrong")
print("All done!")
Example output when 0 is entered:
Enter a number:
0
Invalid input value
All done!
Note
When combining exceptions in a tuple, all specified exceptions are handled by the same code block. This method simplifies your code when similar error handling is required.
Raising Exceptions Inside Functions
Exceptions can be raised within functions, and you can choose to handle them either inside the function or externally by wrapping the function call in a try block.
Handling the Exception Inside the Function
def calculate_user_input():
try:
x = int(input("Enter a number: "))
y = 1 / x
print(y)
except ZeroDivisionError:
print("You cannot divide by zero.")
except:
print("Something else went wrong")
return None
calculate_user_input()
Handling the Exception Outside the Function
def calculate_user_input():
x = int(input("Enter a number: "))
y = 1 / x
print(y)
return None
try:
calculate_user_input()
except ZeroDivisionError:
print("You cannot divide by zero.")
except:
print("Something else went wrong")
For example, if you enter 0, the output will be:
Enter a number:
0
You cannot divide by zero.
Manually Raising Exceptions
You can manually raise exceptions using the raise
keyword. This is useful for testing your error-handling strategy or delegating error processing elsewhere in your application. For instance, the following code manually raises a ZeroDivisionError:
raise ZeroDivisionError
The output will be similar to:
ZeroDivisionError
Consider this scenario where a function always raises a ZeroDivisionError. This code snippet tests the exception handling:
def calculate_user_input():
raise ZeroDivisionError
try:
calculate_user_input()
except ZeroDivisionError:
print("You cannot divide by zero.")
except:
print("Something else went wrong")
For input that leads to an exception, the output will be:
You cannot divide by zero.
Re-raising Exceptions
Sometimes you may need to perform additional actions (like logging) and then allow the exception to propagate upward. In such cases, you can re-raise the exception within an except
block:
def calculate_user_input():
try:
x = int(input("Enter a number: "))
y = 1 / x
print(y)
except:
print("Something else went wrong")
raise # Re-raise the caught exception
return None
calculate_user_input()
Warning
When re-raising exceptions, ensure that you have already performed any necessary cleanup or logging. This practice maintains robust error handling in larger applications.
Using the assert Keyword
The assert
keyword in Python allows you to test if a condition is true. If the condition evaluates to False (or a value considered false, such as 0, an empty string, or None), an AssertionError is raised immediately. This is particularly useful for validating data and ensuring that functions operate on valid inputs.
Consider the following example:
import math
x = int(input("Enter a number: "))
assert x >= 0
result = math.sqrt(x)
print("Result:", result)
Example outputs:
Enter a number:
0
Result: 0.0
Enter a number:
-1
Traceback (most recent call last):
...
AssertionError
Raising an AssertionError in this manner helps ensure that your code does not proceed with invalid data, minimizing the risk of producing erroneous results.
For more detailed information, refer to the Python documentation on built-in exceptions.
That concludes this lesson. Continue practicing and applying these concepts to develop robust error handling in your Python applications.
Watch Video
Watch video content
Practice Lab
Practice lab