Yuliya Yeusiyevich
Yuliya Yeusiyevich

Reputation: 1

Get args names and values of a function

My task is write a decorator which logs information about calls of decorated function, values of its arguments, values of keyword arguments and execution time. Log should be written to a file (log.txt).

Example of using:

@log
def foo(a, b, c):
    pass

foo(1, 2, c=3)

Output:

foo; args: a=1, b=2; kwargs: c=3; execution time: 0.12 sec.

I can't figure out how to extract arg names and values in "name=value" pairs. My code:

def log(fn):
    def wrapper(*args, **kwargs):
        loc = locals()
        t1 = time()
        result = fn(*args, **kwargs)
        end_time = time() - t1
        with open('log.txt', 'w', encoding='utf-8') as f:
            f.write(f'{fn.__name__}; ')
            f.write(f'args: {loc["args"]}; ')
            for key, value in kwargs.items():
                f.write(f'kwargs: {key}={value}; ')
            f.write('execution time: {} sec.'.format(end_time))
        return result
    return wrapper

Output:

foo; args: (1, 2); kwargs: c=3; execution time: 0.0 sec.

Thank you in advance!

Upvotes: 0

Views: 667

Answers (1)

import time

def log(fn):
    
    def log_wrapper(*args, **kwargs):
        # getting arguments
        params = fn.__code__.co_varnames[:fn.__code__.co_argcount]
        params_list = list(params)
        args_list = list(args)
        #   separate keyword arguments
        for key in kwargs.keys():
            if key in params_list:
                params_list.remove(key)
        #   merge positional keys and args
        args_dict = {}
        for key in params_list:
            for arg in args_list:
                args_dict[key] = arg
                args_list.remove(arg)
        print(args_dict)
        print(kwargs)

        # start timer
        st = time.time()

        # Execute function
        result = fn(*args, **kwargs)

        # get execution_time
        run_time = time.time() - st

        # Log function 'fn' name and arguments
        with open("log.txt", "w", encoding="utf-8") as log_file:
            log_file.write(f"{fn.__name__};")
            args_field = ""
            for key, val in args_dict.items():
                args_field += f"{key}={val},"
            args_field = args_field[:-1]
            args_field += ";"
            log_file.write(args_field)
            kwargs_field = ""
            for key, val in kwargs.items():
                kwargs_field += f"{key}={val},"
            kwargs_field = kwargs_field[:-1]
            kwargs_field += ";"
            log_file.write(kwargs_field)
            log_file.write(f"execution time: {run_time} sec.")

    return log_wrapper


@log
def foo(a, b, c):
    return 0


if __name__ == "__main__":
    foo(1, 2, c=3)

log.txt:

foo;a=1,b=2;c=3;execution time: 0.0 sec.

Upvotes: 1

Related Questions