Suppose I have two (or more) functions. One is higher level, processing stuff by calling different other functions. If one of these functions fails (e.g. Math error), I want to "abort" not only that function, but also the ones that called it. In my case I need this to escape an error and avoid having the rest of all calculations done, without quitting the whole process (which would also terminate my GUI). Instead, I want the script to continue running, but back on the upmost level.
This is an abstraction of my original problem:
def levelA(x):
xx = levelB(x=x)
xx *= 2
return xx
def levelB(x):
if x==0: return
y = 10 / x
return y
x = 0
print (levelA(x=x))
Initializing x
with the value 0 would cause a crash in levelB
when 10 is divided by x
. So I first make sure that x
is different from 0. If it's not, the function is aborted by calling return. Now levelA
wants to continue with the doubling of the result of levelB
which, in the case x=0
, is "None" and there we go with another crash.
Of course, what I can do is inserting the line
if xx is None: return
before doing xx *= 2
. But in my real case, there is not just one extra level, but 2 or even 3 and there are many different functions that are called. I want to avoid checking each and every output of the function for errors.
So my question is: Can I somehow go all the way back to the first function call and skip the ones that were in between? Something like a "deep return"?
Exceptions were invented to handle the situation you describe. So, for example:
In [72]: def f1(x):
...: return f2(x)
...:
In [73]: def f2(x):
...: return f3(x)
...:
In [74]: def f3(x):
...: if x > 0:
...: return x
...: else:
...: raise ValueError("f3 called with negative argument")
...:
In [75]: try:
...: print(f1(-2))
...: except ValueError as e:
...: print(e)
...:
f3 called with negative argument