Last active
July 3, 2023 19:04
-
-
Save crizCraig/507e98a6ec6cecd0ed4db7170d540e2b to your computer and use it in GitHub Desktop.
Python timing decorator to measure how long a function takes (handles async and sync)
This file contains 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 asyncio | |
import time | |
from typing import Callable, Any | |
def timed(fn: Callable[..., Any]) -> Callable[..., Any]: | |
""" | |
Decorator log test start and end time of a function | |
:param fn: Function to decorate | |
:return: Decorated function | |
Example: | |
>>> @timed | |
>>> def test_fn(): | |
>>> time.sleep(1) | |
>>> test_fn() | |
""" | |
def wrapped_fn(*args: Any, **kwargs: Any) -> Any: | |
start = time.time() | |
print(f'Running {fn.__name__}...') | |
ret = fn(*args, **kwargs) | |
duration_str = get_duration_str(start) | |
print(f'Finished {fn.__name__} in {duration_str}') | |
return ret | |
async def wrapped_fn_async(*args: Any, **kwargs: Any) -> Any: | |
start = time.time() | |
print(f'Running {fn.__name__}...') | |
ret = await fn(*args, **kwargs) | |
duration_str = get_duration_str(start) | |
print(f'Finished {fn.__name__} in {duration_str}') | |
return ret | |
if asyncio.iscoroutinefunction(fn): | |
return wrapped_fn_async | |
else: | |
return wrapped_fn | |
def get_duration_str(start: float) -> str: | |
"""Get human readable duration string from start time""" | |
duration = time.time() - start | |
if duration > 1: | |
duration_str = f'{duration:,.3f}s' | |
elif duration > 1e-3: | |
duration_str = f'{round(duration * 1e3)}ms' | |
elif duration > 1e-6: | |
duration_str = f'{round(duration * 1e6)}us' | |
else: | |
duration_str = f'{duration * 1e9}ns' | |
return duration_str |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment