1"""A simple timer class to keep record of the elapsed time.""" 2 3import time 4 5 6class TimeRecorder(object): 7 """Main class to keep time records. 8 9 A timer record contains an ID, a start timestamp, and an optional stop 10 timestamps. The elapsed time calculated as stop - start. 11 If the stop timestamp is not set, current system time will be used. 12 13 Example usage: 14 >>> timer = TimeRecorder() 15 >>> # start a single timer, ID = 'lunch' 16 >>> timer.start_timer('lunch') 17 >>> # start two timers at the same time 18 >>> timer.start_timer(['salad', 'dessert']) 19 >>> # stop a single timer 20 >>> timer.stop_timer('salad') 21 >>> # get elapsed time of all timers 22 >>> timer.elapsed() 23 """ 24 25 def __init__(self): 26 self.recorder = dict() 27 28 def start_timer(self, record_ids='Default', force=False): 29 """Start one or more timer. 30 31 Starts one or more timer at current system time with the record ID 32 specified in record_ids. Will overwrite/restart existing timer. 33 34 Args: 35 record_ids: timer record IDs. Can be a string or a list of strings. 36 If the record ID is a list, will start multiple timers 37 at the same time. 38 force: Force update the timer's start time if the specified timer 39 has already started. By default we won't update started timer 40 again. 41 42 Returns: 43 Number of timer started. 44 """ 45 if isinstance(record_ids, str): 46 record_ids = [record_ids] 47 start_time = time.time() 48 for rec in record_ids: 49 if force or rec not in self.recorder: 50 self.recorder[rec] = [start_time, None] 51 return len(record_ids) 52 53 def stop_timer(self, record_ids=None, force=False): 54 """Stop one or more timer. 55 56 Stops one or more timer at current system time. 57 58 Args: 59 record_ids: timer record IDs. Can be a string or a list of strings. 60 If the record ID is a list, will stop multiple timers at 61 the same time. By default, it will stop all timers. 62 force: Force update the timer's stop time if the specified timer has 63 already stopped. By default we won't update stopped timer 64 again. 65 66 Returns: 67 Number of timer stopped. 68 """ 69 # stop all record if id is not provided. 70 if record_ids is None: 71 record_ids = self.recorder.keys() 72 elif isinstance(record_ids, str): 73 record_ids = [record_ids] 74 stop_time = time.time() 75 num_rec = 0 76 for rec in record_ids: 77 if rec in self.recorder: 78 if force or self.recorder[rec][1] is None: 79 self.recorder[rec][1] = stop_time 80 num_rec += 1 81 return num_rec 82 83 def elapsed(self, record_ids=None): 84 """Return elapsed time in seconds. 85 86 For records with no stop time, will calculate based on the current 87 system time. 88 89 Args: 90 record_ids: timer record IDs. Can be a string or a list of strings. 91 If the record ID is a list, will compute the elapsed 92 time for all specified timers. Default value (None) 93 calculates elapsed time for all existing timers. 94 95 Returns: 96 The elapsed time. If the record_ids is a string, will return the 97 time in seconds as float type. If the record_ids is a list or 98 default (None), will return a dict of the <record id, elapsed time>. 99 """ 100 single_record = False 101 if record_ids is None: 102 record_ids = self.recorder.keys() 103 elif isinstance(record_ids, str): 104 record_ids = [record_ids] 105 single_record = True 106 results = dict() 107 curr_time = time.time() 108 for rec in record_ids: 109 if rec in self.recorder: 110 if self.recorder[rec][1] is not None: 111 results[rec] = self.recorder[rec][1] - self.recorder[rec][0] 112 else: 113 results[rec] = curr_time - self.recorder[rec][0] 114 if not results: # no valid record found 115 return None 116 elif single_record and len(record_ids) == 1: 117 # only 1 record is requested, return results directly 118 return results[record_ids[0]] 119 else: 120 return results # multiple records, return a dict. 121 122 def clear(self, record_ids=None): 123 """Clear existing time records.""" 124 if record_ids is None: 125 self.recorder = dict() 126 return 127 128 if isinstance(record_ids, str): 129 record_ids = [record_ids] 130 for rec in record_ids: 131 if rec in self.recorder: 132 del self.recorder[rec] 133