Skip to content

Instantly share code, notes, and snippets.

@ruohola
Last active June 3, 2020 15:16
Show Gist options
  • Save ruohola/0b96a30e67f87217ae28244a7e2ca2e7 to your computer and use it in GitHub Desktop.
Save ruohola/0b96a30e67f87217ae28244a7e2ca2e7 to your computer and use it in GitHub Desktop.
Timer to use as a decorator to time the execution of any Python function
from functools import wraps
from time import perf_counter
from typing import Any, Callable, Optional, TypeVar, cast
F = TypeVar("F", bound=Callable[..., Any])
def timer(prefix: Optional[str] = None, precision: int = 6) -> Callable[[F], F]:
"""Use as a decorator to time the execution of any function.
Args:
prefix: String to print before the time taken.
Default is the name of the function.
precision: How many decimals to include in the seconds value.
Examples:
>>> @timer()
... def foo(x):
... return x
>>> foo(123)
foo: 0.000...s
123
>>> @timer("Time taken: ", 2)
... def foo(x):
... return x
>>> foo(123)
Time taken: 0.00s
123
"""
def decorator(func: F) -> F:
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
nonlocal prefix
prefix = prefix if prefix is not None else f"{func.__name__}: "
start = perf_counter()
result = func(*args, **kwargs)
end = perf_counter()
print(f"{prefix}{end - start:.{precision}f}s")
return result
return cast(F, wrapper)
return decorator
@ruohola
Copy link
Author

ruohola commented Jun 1, 2020

$ python3 -m doctest --verbose -o=ELLIPSIS timer.py && mypy timer.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment