Skip to content

Instantly share code, notes, and snippets.

@crizCraig
Last active July 3, 2023 19:04
Show Gist options
  • Save crizCraig/507e98a6ec6cecd0ed4db7170d540e2b to your computer and use it in GitHub Desktop.
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)
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