Skip to content

decorators

timer

timer(r: int | None = 2, sink: Callable = sys.stdout.write, show_args: bool = False, serialize: bool = False, sep=' | ')

A decorator that displays the time taken for a function to execute.

Parameters:

Name Type Description Default
r int

Number of decimal places to round the time to. Defaults to 2.

2
sink Callable

A function that takes a string and does something with it. Defaults to print.

write
show_args bool

Whether to show the arguments passed to the function. Defaults to False.

False
serialize bool

Whether to serialize the output as JSON. Defaults to False.

False
sep str

Separator between the function/method name and the arguments. Defaults to " | ".

' | '
Source code in stdl/decorators.py
def timer(
    r: int | None = 2,
    sink: T.Callable = sys.stdout.write,
    show_args: bool = False,
    serialize: bool = False,
    sep=" | ",
):
    """
    A decorator that displays the time taken for a function to execute.

    Args:
        r (int, optional): Number of decimal places to round the time to. Defaults to 2.
        sink (Callable, optional): A function that takes a string and does something with it. Defaults to print.
        show_args (bool, optional): Whether to show the arguments passed to the function. Defaults to False.
        serialize (bool, optional): Whether to serialize the output as JSON. Defaults to False.
        sep (str, optional): Separator between the function/method name and the arguments. Defaults to " | ".
    """

    def decorator(func: T.Callable):
        @wraps(func)
        def wrapper(*args, **kwargs):
            time_start = time.perf_counter()
            result = func(*args, **kwargs)

            time_end = time.perf_counter()
            time_elapsed = time_end - time_start
            if r is not None:
                time_elapsed = round(time_elapsed, r)

            is_method = "self" in list(inspect.signature(func).parameters.keys())
            args = args[1:] if is_method else args
            name = func.__qualname__ if is_method else func.__name__
            message = f"'{name}' took {time_elapsed}s"

            if show_args:
                kwargs_info = ", ".join(f"{k}={v}" for k, v in kwargs.items())
                all_args = ", ".join(map(str, args)) + (", " + kwargs_info if kwargs_info else "")
                message += f"{sep}Args: {all_args}"

            if serialize:
                message_dict = {
                    "name": name,
                    "time": time_elapsed,
                    "args": args,
                    "kwargs": kwargs,
                }
                if show_args:
                    message_dict["args"] = args
                    message_dict["kwargs"] = kwargs
                message = json.dumps(message_dict)

            sink(message)
            return result

        return wrapper

    return decorator