A timer context manager in python
20220125205230
When writing code you may want to quickly do a performance analysis on your algorithms. The most likely tool that you need is obviously an profiler (perf_counter ?!) but if that is too much of a hassle to set up, the quickest way is to write your own time measuring tool.
The easiest way of doing it is:
import time
actual_time = time.perf_counter()
comput_time = time.process_time()
result = f(*args, **kw)
actual_time = time.perf_counter() - actual_time
comput_time = time.process_time() - comput_time
Using a function decorator
For a better looking code you may wish to use a decorator if all you need is to print the execution times on stdout
import time
from functools import wraps
def timing(f):
"""
Decorator to be used to measure the time it takes for a single call
"""
@wraps(f)
def wrap(*args, **kw):
actual_time = time.perf_counter()
comput_time = time.process_time()
result = f(*args, **kw)
actual_time = time.perf_counter() - actual_time
comput_time = time.process_time() - comput_time
print(
'[%2.4fs|%2.4fs] func:%r args:[%r, %r]' % (
actual_time,
comput_time,
f.__name__,
args if len(args) < 1000 else "<something large>",
kw
)
)
return result
return wrap
Example:
import time
@timing
def my_heavy_function(a, b):
time.sleep(1)
my_heavy_function(1, "2")
> [1.0011s|0.0014s] func:'my_heavy_function' args:[(1, '2'), {}]
Using a context manager
But if you want to have access to the actual_time
and comput_time
you may want to use context manager (inspired by this thread):
import time
class timer(object):
"""
A small timer context manager
"""
def __enter__(self):
self.actual_time = time.perf_counter()
self.comput_time = time.process_time()
return self
def __exit__(self, type, value, traceback):
self.actual_time = time.perf_counter() - self.actual_time
self.comput_time = time.process_time() - self.comput_time
Example
with timer() as t:
time.sleep(4)
print(t.actual_time, t.comput_time)
> 4.004134978000366 0.0028222399996593595
Comments