Some of my functions use a "fail_silently" flag. It is used in the following way:
def test(a, b, c=1, fail_silently = False)
try:
return int(a) + c
except:
if fail_silently:
return None
raise
Therefore, if there is an error, we catch it and fail gracefully. The key here is that it can be toggled dynamically by whoever is calling it.
I am using this for a many different functions and class methods and thought to make it a decorator.
There are a few problems:
- I want to be able name the flag "raise_exception" or "fail_silently" or "whatever"...
- The flag may or may not have a default value
- The flag may or may not be passed in (usually not)
- It needs to work with class methods too
Thus my decorator needs to look for (assuming the flag is called "fail_silently") the flag in the following locations in this order
- **kwargs (the passed in function arguments), simple dictionary get on flag
- *args - get the positional argument of the flag, then scan for index in args (which might not be there)
- Get the default value of the flag from the function
The problem is the code is now getting really messy and has many points of failure.
def try_except_response(parameter = 'fail_silently'):
def real_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs) # the function itself,
except: # if it raises an Exception!
# check to see if the Flag is in passed in kwargs!
if kwargs.get(parameter)== True:
return None
elif kwargs.get(parameter) == False:
raise
else:
# Flag is not in kwargs, check to see if it is in args
function_args, vargs, kewords, defaults = inspect.getargspec(func) # get the index of argument of interest
try:
argument_index = function_args.index(parameter) # get the index of argument of interest
except ValueError:
raise ValueError('The inputted decorator for "fail_silently" was not found! The behavior will not work.')
if len(args) > argument_index: # check to see if it is inputted
keyword = args[argument_index] # get the value!!
if keyword == True:
return None
elif kwargs == False:
raise
else:
raise ValueError('The "fail_silently" flag did not return a value that we understand. Must be True or False')
else:
# not in args either! let's go get the default value.
# TODO MORE STUFF!!!
raise
raise
raise
return wrapper
What is the best way this can be cleaned up? Or alternatives? I am thinking about implementing a version of locals() that will create a dictionary of all parameters passed into the function and then check from there...
Aucun commentaire:
Enregistrer un commentaire