简体   繁体   中英

Increment name through decorator in Python

I'm trying to make a decorator for logging purposes. I try to increment the name of a log when the same decorator is called inside sub-function but fail to have a correct input. I also have some difficulty understanding my actual output.

import datetime
import functools


def log(func):

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        wrapper.log_name += "." + func.__name__
        start = datetime.datetime.now()
        func(*args, **kwargs)
        duration = datetime.datetime.now() - start
        print(f"{wrapper.log_name }: {duration}")

    wrapper.log_name = "test"

    return wrapper


@log
def main_function():
    other_function()


@log
def other_function():
    print("i'm in the other function")


if __name__ == '__main__':
    main_function()
    main_function()

I got:

i'm in the other function
**test.other_function:** 0:00:00.000007
test.main_function: 0:00:00.000021
i'm in the other function
test.other_function.other_function: 0:00:00.000001
test.main_function.main_function: 0:00:00.000004

But I expected:

i'm in the other function
test.main_function.other_function: 0:00:00.000007
test.main_function: 0:00:00.000021
i'm in the other function
test.main_function.other_function: 0:00:00.000001
test.main_function: 0:00:00.000004

Do you know how to solve this?

Used inspect library to get calling function info from the stack .
* Added other_function2 just to check.

import datetime
import functools
import inspect

def log(func):

    @functools.wraps(func)
    def wrapper(*args, **kwargs):

        # get previous callings from the stack
        previous_callings = []
        stack = inspect.stack()
        for i in range(2, len(stack), 2):
            if stack[i][3] != stack[0][3]: break
            previous_callings.append(stack[i - 1][3])

        start = datetime.datetime.now()
        func(*args, **kwargs)
        duration = datetime.datetime.now() - start
        to_print = ['test'] + previous_callings[::-1] + [func.__name__]
        print(f"{'.'.join(to_print)}: {duration}")

    return wrapper

@log
def main_function():
    other_function()

@log
def other_function():
    print("i'm in the other function")
    other_function2()

@log
def other_function2():
    print("i'm in the other function 2")


if __name__ == '__main__':
    main_function()
    main_function()

Gives Output (Didn't bother to change the time format...)

i'm in the other function
i'm in the other function 2
test.main_function.other_function.other_function2: 0:00:00
test.main_function.other_function: 0:00:00
test.main_function: 0:00:00
i'm in the other function
i'm in the other function 2
test.main_function.other_function.other_function2: 0:00:00
test.main_function.other_function: 0:00:00
test.main_function: 0:00:00

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM