Advertisement
Guest User

Untitled

a guest
Jun 20th, 2019
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.87 KB | None | 0 0
  1. from time import time
  2. from threading import Lock
  3.  
  4. '''
  5.  
  6. #Description
  7.  
  8. A Timer class that automatically prints (or logs using a provided logger) and returns relative and absolute times since last and first call.
  9. Implements empty laps and hierarchichal timings.
  10. Time-steps can easily be named by adding a string to the timer call : timer('a step name') (the behavior is the same of for print: multilple args will be seperated by a space).
  11.  
  12. get_timer works like the python logging class : it will create a new Timer or get one that already exists based on the required name.
  13. get_timer is also safe for concurrency.
  14.  
  15. #Usage
  16.  
  17. ```
  18. from time import sleep
  19. from timer import get_timer
  20.  
  21. def demo_function():
  22. timer = get_timer('Doing Something', remember=True)
  23.  
  24. #...doing something 1
  25. sleep(1)
  26. timer('doing something 1')
  27.  
  28. for i in range(2):
  29. #...doing some sub process
  30. sleep(0.5)
  31. timer.sub('doing subprocess',i)
  32.  
  33. sleep(2)
  34. #... doing some background process
  35. timer.empty_lap() # next relative measurement will be measured from here on out
  36.  
  37. #...doing something 2
  38. sleep(1)
  39. timer('doing all things')
  40.  
  41. timer.summary()
  42.  
  43. if __name__ == '__main__':
  44. demo_function()
  45. ```
  46.  
  47. Demo function will output :
  48.  
  49. Timer - Doing Something --- doing something 1 took 1.0012 seconds (1.0012).
  50. Timer - Doing Something --- doing subprocess 0 took 0.5009 seconds (1.502).
  51. Timer - Doing Something --- doing subprocess 1 took 0.5008 seconds (2.0028).
  52. Timer - Doing Something --- doing all things took 1.0011 seconds (5.0058).
  53. Timer summary:
  54. -- origin: 1560152644.2148
  55. -- doing something 1: 1560152645.216
  56. -- doing all things: 1560152649.2207
  57.  
  58. '''
  59.  
  60. class TimerManager():
  61.  
  62. def __init__(self):
  63. self.timers = {}
  64. self.lock = Lock()
  65.  
  66. manager = TimerManager()
  67.  
  68. def get_timer(name, verbose = 1, logger = None, remember = False):
  69. try :
  70. manager.lock.acquire()
  71. if name in manager.timers:
  72. return manager.timers[name]
  73. else:
  74. timer = Timer(name,verbose,logger,remember)
  75. manager.timers[name] = timer
  76. return timer
  77. except Exception as err:
  78. print('WARNING : get_timer lock acquisition raised {}. Timer may be overwritten...'.format(err))
  79. timer = Timer(name,verbose,logger,remember)
  80. manager.timers[name] = timer
  81. return timer
  82. finally:
  83. manager.lock.release()
  84.  
  85. class Timer():
  86. ''' A handy all-round Timer class.
  87.  
  88. # Args:
  89. - name (optionnal) : the timer name, if provided, will be prefixed to all messages
  90. - verbose (default = 1). If set to 0, timer will never print messages but only return relative and absolute time measurements.
  91. - logger (optionnal) : a logger to redirect prints
  92. - remember (default = False) : if set to True, all timesteps will be kept in a list.
  93. - round (default True) : if True, times will be rounded upon display for prettier prints
  94.  
  95. Not safe for concurrency.
  96. '''
  97.  
  98. def __init__(self, name = None, verbose = 1, logger = None, remember = False, round_off = True):
  99.  
  100. self.origin = time()
  101.  
  102. self.current = self.origin
  103.  
  104. self.sub_current = self.current
  105.  
  106. self.ouput = logger.info if logger else print
  107.  
  108. self.verbose = verbose
  109.  
  110. self.name = name
  111. self.prefix = '' if name is None else '{} --- '.format(name)
  112.  
  113. self.round = ( lambda x : round(x,4) ) if round_off else lambda x : x
  114.  
  115. self.remember = remember
  116. if self.remember:
  117. self.steps = [ ('origin',self.origin) ]
  118.  
  119. def step(self,*args):
  120. current = time()
  121.  
  122. message = ' '.join([str(arg) for arg in args])
  123.  
  124. delta = current - self.current
  125. absolute = current - self.origin
  126.  
  127. if self.verbose > 0 :
  128. self.ouput('Timer - {}{} took {} seconds ({}).'.format(self.prefix, message,self.round(delta), self.round(absolute)))
  129.  
  130. self.current = current
  131. self.sub_current = current
  132.  
  133. if self.remember:
  134. self.steps.append((message,current))
  135.  
  136. return delta,absolute
  137.  
  138. def empty_lap(self):
  139. self.current = time()
  140.  
  141. def sub(self,*args):
  142. current = time()
  143. message = ' '.join([str(arg) for arg in args])
  144. delta = current - self.sub_current
  145. absolute = current - self.origin
  146. if self.verbose > 0:
  147. self.ouput('Timer - {}{} took {} seconds ({}).'.format(self.prefix, message,self.round(delta), self.round(absolute)))
  148. self.sub_current = current
  149. return delta,absolute
  150.  
  151. def summary(self):
  152. if self.remember:
  153. if self.verbose>0:
  154. print('\n'.join(['Timer summary:']+['-- {}: {}'.format(s,self.round(t)) for s,t in self.steps]))
  155. return self.steps
  156. return None
  157.  
  158. def __call__(self,*args):
  159. self.step(*args)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement