The raise function
As our code can generate its own exceptions during execution, we can also manually trigger an exception to occur with the built-in raise() function. The raise() method is often used to raise an exception to the function that called it. While this may seem unnecessary, in larger programs, this can actually be quite useful.
Imagine a function, function_b(), which receives parsed data in the form of a packet from function_a(). Our function_b() function does some further processing on the packet and then calls function_c() to continue to process the packet. If function_c() raises an exception back to function_b(), we might design some logic to alert the user of the malformed packet instead of trying to process it and producing faulty results. The following is some pseudocode representing such a scenario:
001 import module
002
003 def main():
004 function_a(data)
005
006 def function_a(data_in):
007 try:
008 # parse data into packet
009 function_b(parsed_packet)
010 except Exception as e:
011 if isinstance(e, ErrorA):
012 # Address this type of error
013 function_b(fixed_packet)
014 [etc.]
015
016 def function_b(packet):
017 # Process packet and store in processed_packet variable
018 try:
019 module.function_c(processed_packet)
020 except SomeError:
021 # Error testing logic
022 if type 1 error:
023 raise ErrorA()
024 elif type 2 error:
025 raise ErrorB()
026 [etc.]
027
028 if __name__ == '__main__':
029 main()
In addition, raising custom or built-in exceptions can be useful when dealing with exceptions that Python doesn't recognize on its own. Let's revisit the example of the malformed packet. When the second function received the raised error, we might design some logic that tests some possible sources of error. Depending on those results, we might raise different exceptions back to the calling function, function_a().
When raising a built-in exception, make sure to use an exception that most closely matches the error. For example, if the error revolves around an index issue, use the IndexError exception. When raising an exception, we should pass in a string containing a description of the error. This string should be descriptive and help the developer identify the issue, unlike the following string that's used. The adage do what we say, not what we do applies here, as we are simply demonstrating functionality:
>>> def raise_error():
... raise TypeError('This is a TypeError')
...
>>> raise_error()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in raise_error
TypeError: This is a TypeError