|
""" |
|
Module execution_timer provides an ExecutionTimer class |
|
to measure the execution time of a code block. |
|
It offers two usage options: as a context manager and as a decorator. |
|
|
|
* Example usage as a context manager: |
|
with ExecutionTimer(): |
|
main() |
|
|
|
* Example usage as a decorator: |
|
@execution_timer |
|
def main(): |
|
# Code block to measure execution time |
|
""" |
|
|
|
from datetime import datetime |
|
from time import perf_counter_ns |
|
|
|
from dataclasses import dataclass |
|
from rich.console import Console |
|
|
|
|
|
@dataclass(slots=True) |
|
class ExecutionTimer: |
|
""" |
|
ExecutionTimer is a context manager that measures the execution time of a code block. |
|
It captures the start time, end time, and duration of the code block. |
|
""" |
|
|
|
start_date: datetime = None |
|
end_date: datetime = None |
|
start_time_ns: int = None |
|
end_time_ns: int = None |
|
console: Console = Console() |
|
|
|
def __post_init__(self): |
|
self.start_date = datetime.now() |
|
self.start_time_ns = perf_counter_ns() |
|
|
|
def __enter__(self) -> 'ExecutionTimer': |
|
return self |
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb): |
|
try: |
|
self.end_date = datetime.now() |
|
self.end_time_ns = perf_counter_ns() |
|
self.display_time() |
|
except AttributeError: |
|
print('An error occurred: __exit__') |
|
|
|
@staticmethod |
|
def current_datetime(date: datetime) -> str: |
|
""" |
|
Formats a datetime object as a string in the format 'YYYY-MM-DD HH:MM:SS'. |
|
""" |
|
|
|
return f'[yellow]{date.year}-{date.month:02d}-{date.day:02d}' \ |
|
f' [white bold]{date.hour:02d}:{date.minute:02d}:{date.second:02d}' |
|
|
|
def calculate_duration(self) -> str: |
|
""" |
|
Calculates the duration of the code block in hours, minutes, seconds, milliseconds, |
|
microseconds, and nanoseconds. |
|
""" |
|
|
|
duration_ns: int = self.end_time_ns - self.start_time_ns |
|
duration_s, duration_ns = map(int, divmod(duration_ns, 1_000_000_000)) |
|
duration_ms, duration_ns = map(int, divmod(duration_ns, 1_000_000)) |
|
duration_us, duration_ns = map(int, divmod(duration_ns, 1_000)) |
|
|
|
hours, remainder = map(int, divmod(duration_s, 3600)) |
|
minutes, seconds = map(int, divmod(remainder, 60)) |
|
|
|
return f'[white bold]{hours:02d}:{minutes:02d}:{seconds:02d}:' \ |
|
f'{duration_ms:03d}:{duration_us:03d}:{duration_ns:03d}' |
|
|
|
def calculate_duration_alt(self) -> tuple[float, ...]: |
|
""" |
|
Calculates the duration of the code block in hours, minutes, and seconds |
|
using an alternative method. |
|
""" |
|
|
|
duration_ns: int = self.end_time_ns - self.start_time_ns |
|
hours_alt: float = duration_ns / 1_000_000_000 / 60 / 60 |
|
minutes_alt: float = duration_ns / 1_000_000_000 / 60 |
|
seconds_alt: float = duration_ns / 1_000_000_000 |
|
|
|
return hours_alt, minutes_alt, seconds_alt |
|
|
|
def display_time(self): |
|
""" |
|
Displays the start date, end date, and duration of the code block execution. |
|
""" |
|
|
|
start_date_str: str = self.current_datetime(self.start_date) |
|
end_date_str: str = self.current_datetime(self.end_date) |
|
duration: str = self.calculate_duration() |
|
hours_alt, minutes_alt, seconds_alt = map( |
|
float, self.calculate_duration_alt()) |
|
|
|
self.console.print( |
|
'\n[bold white]ββββββββββββ EXECUTION TIME ββββββββββββ') |
|
self.console.print( |
|
'[bold bright_yellow] YYYY-MM-DD HH:MM:SS:ms :Β΅s :ns') |
|
self.console.print( |
|
f'[bright_red bold][[bold white]START[bright_red bold]] {start_date_str}') |
|
self.console.print( |
|
f'[bright_red bold][[bold white]END[bright_red bold]] {end_date_str}') |
|
self.console.print( |
|
f'[bright_red bold][[bold white]TIME[bright_red bold]] [bold bright_yellow]YYYY-MM-DD {duration}') |
|
self.console.print('[bright_red bold] ^^^^^^^^^^^^') |
|
self.console.print( |
|
f'[bright_red bold][[bold white]TIME[bright_red bold]] [white bold]{hours_alt:.9f} hours') |
|
self.console.print( |
|
f'[bright_red bold][[bold white]TIME[bright_red bold]] [white bold]{minutes_alt:.9f} minutes') |
|
self.console.print( |
|
f'[bright_red bold][[bold white]TIME[bright_red bold]] [white bold]{seconds_alt:.9f} seconds') |
|
|
|
|
|
def execution_timer(func): |
|
""" |
|
Decorator that measures the execution time of a function using ExecutionTimer. |
|
""" |
|
|
|
def wrapper(*args, **kwargs): |
|
with ExecutionTimer(): |
|
result = func(*args, **kwargs) |
|
return result |
|
|
|
return wrapper |
|
|