Created
July 27, 2022 00:57
-
-
Save TVect/8a3fadbe157e3458ee997af9eb4977f6 to your computer and use it in GitHub Desktop.
Python Timer Functions: Three Ways to Monitor Your Code https://realpython.com/python-timer/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import time | |
| from contextlib import ContextDecorator | |
| from dataclasses import dataclass, field | |
| from typing import Any, Callable, ClassVar, Dict, Optional | |
| class TimerError(Exception): | |
| """A custom exception used to report errors in use of Timer class""" | |
| @dataclass | |
| class Timer(ContextDecorator): | |
| """Time your code using a class, context manager, or decorator""" | |
| timers: ClassVar[Dict[str, float]] = {} | |
| name: Optional[str] = None | |
| text: str = "Elapsed time: {:0.4f} seconds" | |
| logger: Optional[Callable[[str], None]] = print | |
| _start_time: Optional[float] = field(default=None, init=False, repr=False) | |
| def __post_init__(self) -> None: | |
| """Initialization: add timer to dict of timers""" | |
| if self.name: | |
| self.timers.setdefault(self.name, 0) | |
| def start(self) -> None: | |
| """Start a new timer""" | |
| if self._start_time is not None: | |
| raise TimerError(f"Timer is running. Use .stop() to stop it") | |
| self._start_time = time.perf_counter() | |
| def stop(self) -> float: | |
| """Stop the timer, and report the elapsed time""" | |
| if self._start_time is None: | |
| raise TimerError(f"Timer is not running. Use .start() to start it") | |
| # Calculate elapsed time | |
| elapsed_time = time.perf_counter() - self._start_time | |
| self._start_time = None | |
| # Report elapsed time | |
| if self.logger: | |
| self.logger(self.text.format(elapsed_time)) | |
| if self.name: | |
| self.timers[self.name] += elapsed_time | |
| return elapsed_time | |
| def __enter__(self) -> "Timer": | |
| """Start a new timer as a context manager""" | |
| self.start() | |
| return self | |
| def __exit__(self, *exc_info: Any) -> None: | |
| """Stop the context manager timer""" | |
| self.stop() | |
| if __name__ == "__main__": | |
| # 1. As a class: | |
| t = Timer(name="class") | |
| t.start() | |
| # Do something | |
| t.stop() | |
| # 2. As a context manager: | |
| with Timer(name="context manager"): | |
| # Do something | |
| pass | |
| # 3. As a decorator: | |
| @Timer(name="decorator") | |
| def stuff(): | |
| # Do something | |
| pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment