Python Decorator - inspecting function argument values 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) &gt; 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... 

There are simplifying assumptions we can make, but that would require the person writing the function to know something ('flag is always last argument, or default value is always False...'), but I am hoping to get the decorator to be as transparent as possible so it just "works" and lets the function be a function (or class method)
I'm not a fan of this design. @TheBlackCat is right. Don't do this.

If you are to do this, rethink your design. A more sensible one might look like

import functools
from contextlib import suppress

def try_except_response(func):
    @functools.wraps(func)
    def wrapper(*args, fail_silently, **kwargs):
        if fail_silently:
            with suppress(Exception):
                return func(*args, **kwargs)
        else:
            return func(*args, **kwargs)

    return wrapper


The key principle here is KISS.

Note that I'm suppressing Exception, not BaseException, since catching SystemExit and KeyboardInterrupt is almost always a bad idea.

If you want to make fail_silently a default argument, just use another wrapper:

def default_fail_silently(default):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, fail_silently=default, **kwargs):
            return func(*args, fail_silently=fail_silently, **kwargs)
        return wrapper
    return decorator


Then you can do

@default_fail_silently(False)
@try_except_response
def test(a, b, c=1)
    return int(a) + c


This does mean there's more boilerplate, since it exists for each piece of functionality you add, but the logic itself is an order of magnitude simpler.