Don't mind if I give my shot ? def work(i): """ Dummy process function, which takes a random time in the interval 0.0-0.5 secs to execute """ print "Work step %d" % i time.sleep(0.5 * random.random())
def workAll(work, verbose=True, max_iter=20, progress_interval=1.0): ''' pass the real job as a callable ''' progress = time.time() for i in range(max_iter): # do the requested loop work(i) if verbose: print "Work through all %d steps reporting progress every %3.1f secs..." %(max_iter, progress_interval) interval = time.time()-progress if interval>progress_interval: print "Processed %d of %d at pace %s" % (i, max_iter, interval) progress +=interval if __name__=="__main__": workAll(work, False) It's works fine, and the "pace" is 'almost' the required one. You earn a no-thread-mess, and cleaner alg. But the loop is controlled by the caller (the WorkAll function) this is also called ass-backward algorithm, and you cannot expect algorithms to be assbackward (even if it's the best way to implement them). You can use the yield statement, to turn easilly your alg into a nice, stopable assbackward algo: def work(): """ Dummy process function, which takes a random time in the interval 0.0-0.5 secs to execute """ for i in range(50): print "Work step %d" % i time.sleep(0.5 * random.random()) yield i # kind-of "publish it and let the caller do whatever it want s (good practice anyway) def workAll(work, verbose=True, max_iter=20, progress_interval=1.0): ''' pass the real job as a generator ''' progress = time.time() i = 0 for w in work: # do the requested loop if verbose: print "Work through all %d steps reporting progress every %3.1f secs..." %(max_iter, progress_interval) interval = time.time()-progress if interval>progress_interval: print "Processed %d at pace %s" % (w, interval) progress +=interval if i>=max_iter: work.close() i+=1 if __name__=="__main__": workAll(work(), False) # note the calling difference hope it helps. -- http://mail.python.org/mailman/listinfo/python-list