How to catch the input argument of a function in a dict

时间:2017-08-05 11:04:15

标签: python python-3.x function inspect

For logging purpose I tried to automatically catch the arguments passed to a function inside this function and convert them to a dict of arg : value. I tried the inspect.signature() module but it only provides with the default input of the function and not the argument passed to it

import inspect

def my_add_func(a, b ,c=3):
    sig = inspect.signature(my_add_func)
    print("my_add_func args : {0}".format(sig))
    return a + b + c

if __name__ == '__main__':
    my_add_func(10, 2, 3)

Outputs:

(a, b, c=3)

Whereas I would like to have:

{a: 10, b: 2, c:3}

How can I do that?

2 个答案:

答案 0 :(得分:1)

You could use signature.bind:

import inspect

def my_add_func(a, b ,c=3):
    sig = inspect.signature(my_add_func)
    print("my_add_func args : {0}".format(sig.bind(a, b, c)))  # changed here
    return a + b + c

if __name__ == '__main__':
    my_add_func(10, 2, 3)

which gives:

my_add_func args : <BoundArguments (a=10, b=2, c=3)>

If you want it as a mapping (dict-like) you can access the BoundArguments.arguments property:

>>> sig.bind(a, b, c).arguments
OrderedDict([('a', 10), ('b', 2), ('c', 3)])

or even convert it to a plain dict:

>>> dict(sig.bind(a, b, c).arguments))
{'a': 10, 'b': 2, 'c': 3}

答案 1 :(得分:0)

You should use wrappers if you want to log function inputs:

import inspect

def log_args(func):
    def log_and_call(*args, **kwargs):
        sig = inspect.signature(func)
        bound_args = sig.bind(*args, **kwargs)
        bound_args.apply_defaults()
        loggable_args = bound_args.arguments

        print("Function name: " + func.__name__)
        for key, val in loggable_args.items():
            print(key + " = " + str(val))

        return func(*args, **kwargs)
    return log_and_call

@log_args
def do_sum(a, b, c=0):
    return a + b + c


x = do_sum(1,b=2)

This way it is easy to log every function call, and it prevents boilerplate code.
Notice that I used apply_defaults so it will print the value of the default arguments, if not provided with different values.
In the example I also gave the name of b although it is not an argument with a default value, just to show it works.
You can replace the prints with writes to a logger or something similar.