Reputation: 1
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
Reputation: 9
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