I am creating a decorator that catches a raised error in it's target function, and allows the user to continue executing the script (bypassing the function) or drop out of the script.
def catch_error(func):
"""
This decorator is used to make sure that if a decorated function breaks
in the execution of a script, the script doesn't automatically crash.
Instead, it gives you the choice to continue or gracefully exit.
"""
def caught(*args):
try:
return func(*args)
except Exception as err:
question = '\n{0} failed. Continue? (yes/no): '.format(func.func_name)
answer = raw_input(question)
if answer.lower() in ['yes','y']:
pass
else:
print " Aborting! Error that caused failure:\n"
raise err
return None
return caught
Notice that, if the user chooses to bypass the error-returning function and continue executing the script, the decorator returns None. This works well for functions that only return a single value, but it is crashing on functions that attempt to unpack multiple values. For instance,
# Both function and decorator return single value, so works fine
one_val = decorator_works_for_this_func()
# Function nominally returns two values, but decorator only one, so this breaks script
one_val, two_val = decorator_doesnt_work_for_this_func()
Is there a way that I can determine the number of values my target function is supposed to return? For instance, something like:
def better_catch_error(func):
def caught(*args):
try:
return func(*args)
except Exception as err:
...
num_rvals = determine_num_rvals(func)
if num_rvals > 1:
return [ None for count in range(num_rvals) ]
else:
return None
return caught
As always, if there is a better way to do this sort of thing, please let me know. Thanks!
UPDATE:
Thanks for all the suggestions. I decided to narrow the scope of catch_error to a single class of functions, which only return one string value. I just split all the functions returning more than one value into separate functions that return a single value to make them compatible. I had been hoping to make catch_error more generic (and there were several helpful suggestions on how to do that), but for my application it was a little overkill. Thanks again.