Skip to content

Timer module

Utilities to time code:

  • a Timer class that can be used as a context manager
  • a timeit decorator for functions.

Timer

A timer that can be started, stopped, and reset as needed by the user. It keeps track of the total elapsed time in the elapsed attribute::

Examples:

>>> with Timer() as t:
>>>  ....
>>> print(f"... took {t.elapsed} seconds")

use Timer(time.process_time) to get only CPU time.

can also do:

Examples:

>>> t = Timer()
>>> t.start()
>>> t.stop()
>>> t.start()   # will add to the same counter
>>> t.stop()
>>> print(f"{t.elapsed} seconds total")
Source code in bs_python_utils/Timer.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class Timer:
    """
    A timer that can be started, stopped, and reset as needed by the user.
    It keeps track of the total elapsed time in the `elapsed` attribute::

    Examples:
        >>> with Timer() as t:
        >>>  ....
        >>> print(f"... took {t.elapsed} seconds")

    use `Timer(time.process_time)` to get only CPU time.

    can also do:

    Examples:
        >>> t = Timer()
        >>> t.start()
        >>> t.stop()
        >>> t.start()   # will add to the same counter
        >>> t.stop()
        >>> print(f"{t.elapsed} seconds total")
    """

    def __init__(self, func: Callable = time.perf_counter) -> None:
        self.elapsed = 0.0
        self._func = func
        self._start = None

    def start(self) -> None:
        if self._start is not None:
            raise RuntimeError("Already started")
        self._start = self._func()

    def stop(self) -> None:
        if self._start is None:
            raise RuntimeError("Not started")
        end = self._func()
        self.elapsed += end - self._start
        self._start = None

    def reset(self) -> None:
        self.elapsed = 0.0

    @property
    def running(self) -> bool:
        return self._start is not None

    def __enter__(self) -> Any:
        self.start()
        return self

    def __exit__(self, *args: Iterable) -> None:
        self.stop()

timeit(func)

Decorator to time a function

Source code in bs_python_utils/Timer.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def timeit(func: Callable) -> Callable:
    """
    Decorator to time a function
    """

    @wraps(func)
    def wrapper(*args: Iterable, **kwargs: dict) -> Any:
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        print(f"{func.__name__} executed in {end - start:.3f} seconds")
        return result

    return wrapper