I implemented a convenience class to time code execution and print it to the user. This is part of a bigger project that will be distributed to external users. The timer however is only called by other procedures, not by the user directly. I was interested in implementing this myself, so I'm not looking for an external module or similiar. Docstrings are omitted here, the functions are rather straightforward.
from time import perf_counter
class Timer:
def __init__(self, default_round_digits: int = 5):
self.default_digits = default_round_digits
self.start_timer()
def start_timer(self) -> None:
self.start_time = perf_counter()
self.pause_start_time = None
self.pause_length = 0
def pause_timer(self) -> None:
self.pause_start_time = perf_counter()
def resume_timer(self) -> None:
if self.pause_start_time is not None:
self.pause_length += perf_counter() - self.pause_start_time
self.pause_start_time = None
@property
def elapsed_seconds(self) -> float:
# If timer is paused only consider time up to self.pause_start_time instead of now
if self.pause_start_time is not None:
return self.pause_start_time - self.start_time - self.pause_length
else:
return perf_counter() - self.start_time - self.pause_length
def get_timer(self, round_digits: int = None, print_text: str = None, restart: bool = False) -> float:
if round_digits is None:
round_digits = self.default_digits
elapsed_seconds = round(self.elapsed_seconds, ndigits=round_digits)
if print_text is not None:
print(f"{print_text}{elapsed_seconds} seconds")
if restart:
self.start_timer()
return elapsed_seconds
def __str__(self) -> str:
state = "Running" if self.pause_start_time is None else "Paused"
return f"{state} Timer at {self.get_timer()} seconds"
I'm still unsure about initializing attributes outside of __init__
. I know it's not recommended, but copying start_timer
into __init__
seemed like the worse option to me.