Sorry for the possible duplication of a question. Unfortunately, I could not find an answer that is convenient for me.
I want to write a class to calculate the execution time (the mean and the rms of execution time) of a code in the manner of %timeit
in ipython.
For this, I used this code https://stackoverflow.com/a/28218696/5328802 to use in with
statement.
Here is the test:
from TimingManager import TimingManager
import numpy as np
N = 10000
def myfunction1():
l = [i**2 for i in range(N)]
def myfunction2():
l = np.arange(N)**2
print("List test")
with TimingManager(fun=yourfunction1,repeat=10) as t:
t.start()
print("Array test")
with TimingManager(fun=yourfunction2, repeat=10) as t:
t.start()
And here is my realisation of TimingManager
class (file TimingManager.py
):
import timeit
import statistics
class TimingManager():
"""Context Manager used with the statement 'with' to time some execution.
Example:
from TimingManager import TimingManager
with TimingManager(fun=yourfunction,repeat=10) as t:
t.start()
"""
clock = timeit.default_timer
def __init__(self,fun,repeat=10):
self.repeat = repeat
self.time_table = []
self.run = fun
def start(self):
for i in range(self.repeat):
self.timestart = self.clock()
self.run()
self.time_table.append(self.clock() - self.timestart)
def __enter__(self):
""" action on start """
self.timestart = self.clock()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
""" action on exit """
self.print_process_stat()
return False
def print_process_stat(self):
tc = statistics.mean(self.time_table)
dt = statistics.pstdev(self.time_table)
print("Execution time is %s ± %s"%(time_conversion(tc),time_conversion(dt)))
def time_conversion(t):
if t < 1e-9:
return "%4.3g ps" % (t/1e-12)
elif t < 1e-6:
return "%4.3g ms" % (t/1e-9)
elif t < 1e-3:
return "%4.3g μs" % (t/1e-6)
elif t < 1:
return "%4.3g ms" % (t/1e-3)
elif t < 60:
return "%4.3g s" % (t)
elif t < 3600:
return "%2d min %2d s" % (t//60,t%60)
elif t < 24*3600:
return "%2d h %2d min" % (t//3600,(t/60)%60)
else:
return "%2d d %2d h" % (t//(24*3600),(t/60)%60)
It gives me statistics on the calculation time of what I need. But in my opinion this is not elegant. So my question is, is it possible to implement this procedure in a more elegant way (without defining the myfunction
), namely to access the block after the with
statement (perhaps using the content manager) to repeat it inside the TimingManager
class? To use finally something like this:
with TimingManager(repeat=10):
Statemet1
Statemet2
..