Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python timer decorator with outputting classname

I am creating a little helper tool. It is a timer decorator (not so special) for measuring the execution times of any method.

It prints the calculated execution time on the console with useful informations.


def timer(func):
    """@timer decorator"""
    from functools import wraps
    from time import time

    def concat_args(*args, **kwargs):
        for arg in args:
            yield str(arg)
        for key, value in kwargs.items():
            yield str(key) + '=' + str(value)

    @wraps(func)  # sets return meta to func meta
    def wrapper(*args, **kwargs):
        start = time()
        ret = func(*args, **kwargs)
        dur = format((time() - start) * 1000, ".2f")
        print('{}{}({}) -> {}ms.'.format(
            func.__module__ + '.' if func.__module__ else '',
            func.__name__,
            ', '.join(concat_args(*args, **kwargs)),
            dur
            ))
        return ret
    return wrapper

This gives me the modelname, and the functionname like that:

user.models.get_matches(demo) -> 24.09ms.

I want to have the class name in the output, too:

user.models.User.get_matches(demo) -> 24.09ms.

How can I get the class name of the function ('func') from inside the wrapper?


Edit: Great thanks to Hao Li. Here is the finished version:

def timer(func):
    """@timer decorator"""
    from functools import wraps
    from time import time

    def concat_args(*args, **kwargs):
        for arg in args:
            yield str(arg)
        for key, value in kwargs.items():
            yield str(key) + '=' + str(value)

    @wraps(func)  # sets return meta to func meta
    def wrapper(*args, **kwargs):
        start = time()
        ret = func(*args, **kwargs)
        dur = format((time() - start) * 1000, ".2f")
        print('{}{}({}) -> {}ms.'.format(
            func.__module__ + '.' if func.__module__ else '',
            func.__qualname__,
            ', '.join(concat_args(*args, **kwargs)),
            dur,
            ))
        return ret
    return wrapper
like image 231
Frank Avatar asked Jun 21 '20 21:06

Frank


1 Answers

If you are using Python 3

Try to use func.__qualname__ instead of func.__name__.

If you are using Python 2

Try to use func.im_class.__name__ to get the name of the class.

Reference: PEP 3155

like image 86
Hao Li Avatar answered Nov 12 '22 13:11

Hao Li