Probably you have used a shortcut construct like that:
def conditional_result(switch): if switch: return result_a return result_b
Obviously, an else
is not required, because the execution flow leaves the function once it comes across a return
statement. Have you ever felt doing the same with exceptions? In other words:
def conditional_error(switch): if switch: raise ErrorA raise ErrorB
Does that work the same way? Sure. Sure? After ErrorA
is raised — can the execution sequence ever magically re-enter the function conditional_error
right below the if
block, where it was exceptionally left? Generators can do this (with the yield
statement) .
The answer is that the above code is safe and behaves as expected, analogous to the conditional_result
function. The explanation from A Programmer’s Introduction to Python:
The raise statement does two things: it creates an exception object, and immediately leaves the expected program execution sequence to search the enclosing try statements for a matching except clause. The effect of a raise statement is to either divert execution in a matching except suite, or to stop the program because no matching except suite was found to handle the exception.
For the conditional_error
function above this means: if there is a matching except clause, it is outside of the function (there definitely is no handler within the function, do you see one?). In this case the execution flow steps out of the function without saving the current state (as a generator or a co-routine in general would do) — the function is really, absolutely left and the program proceeds at a different point: the matching except clause. If there is no matching except clause, the program stops.
This is how it looks live:
class ErrorA(Exception): pass class ErrorB(Exception): pass def conditional_error(switch): if switch: raise ErrorA raise ErrorB try: conditional_error(True) except ErrorA: print("error A caught!") try: conditional_error(False) except ErrorB: print("error B caught!") conditional_error(False)
With the following output:
$ python test.py error A caught! error B caught! Traceback (most recent call last): File "test.py", line 26, in <module> conditional_error(False) File "test.py", line 11, in conditional_error raise ErrorB __main__.ErrorB
Leave a Reply