Best way to report progress at fixed intervals

eric eric at ericaro.net
Wed Dec 10 06:08:05 EST 2008


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.




More information about the Python-list mailing list