Progress indication

Provides thread safe printing of progress indication to stdout.

Module with couple of classes and couple of functions. Target audience would be 'die hard' command line (DOS 'box') scripters that might want to see some kind of progress indication while their script is crunching long tasks (like while zipping/copying/moving really big files). Python 2.0 and higher is requirement, as is at least very basic Python skill set in order to effectively use it. This module comes with a self test. If run stand alone, it will display few possible 'DOS style' animations while the main thread does its 'heavy' work. In this demo, main thread just sleeps, but pass it a function written in Python, and it will execute it. While it does so, you will be watching animated sequence of \|/ or sequence of dots (better that staring at 'frozen' cursor). Interestingly, script is cross platform and runs on all platforms that provide support for multithreading and where at the same time Python port exists. Classes: Spinner([speed]) Dotter([speed]) By calling 'stop()' method on either of them, calling (main) thread will interrupt Spinner or Dotter and will cause it to end prematurely. (even if it was in the middle of 'sleep-wait-for-the- next-timeout') Wrapper Functions: spinIt(workHorseFnct, *args, **kwargs) dotItSlow(workHorseFnct, *args, **kwargs) dotItFast(workHorseFnct, *args, **kwargs) Preferred way of using progress indicator is through wrapper functions. sys.stdout.write(msg1) spinIt(longRunningProc, *args, **kwargs) # 'prints' animated progress # indicator to stdout or sys.stdout.write(msg1) dotItSlow(longRunningProc, *args, **kwargs) or sys.stdout.write(msg1) dotItFast(longRunningProc, *args, **kwargs) Alternativley, instances of progress indicator classes (Spinner and Dotter) can be invoked and controlled directly: indicator = Spinner(speed=0.1) indicator.start() # Prints 'animated' /|\ sequence in place. ... # Start long running process in your main thread indicator.stop() # Blocking call - will return when indicator dies. indicator = Dotter(speed=1) indicator.start() # Prints 'animated' sequence of dots - one per sec. ... # Start long running process in your main thread indicator.stop() # Blocking call - will return when indicator dies.

File Name : spin.py
Requirement : Python
Author : Branimir Petrovic
Submitted : 10/02/2003
Category : Python
############################################################
#	FileName	spin.py
__author__ =	"Branimir Petrovic"
__version__ =	"1.0.0"
__date__ =		"1 Feb 2003"
############################################################

import sys, threading, time

class ProgressBase(threading.Thread):
    """Base class - not to be instanciated."""

    def __init__(self):
        self.rlock = threading.RLock()
        self.cv = threading.Condition()
        threading.Thread.__init__(self)
        self.setDaemon(1)

    def __backStep(self):
        if self.inplace: sys.stdout.write('\b \b')

    def __call__(self):
        self.start()

    def start(self):
        self.stopFlag = 0
        threading.Thread.start(self)

    def stop(self):
        """To be called by the 'main' thread: Method will block
        and wait for the thread to stop before returning control
        to 'main'."""

        self.stopFlag = 1

        # Wake up 'Sleeping Beauty' ahead of time (if it needs to)...
        self.cv.acquire()
        self.cv.notify()
        self.cv.release()

        # Block and wait here untill thread fully exits its run method.
        self.rlock.acquire()



class Spinner(ProgressBase):
    """Print 'animated' /|\ sequence to stdout in separate thread"""

    def __init__(self, speed=0.1):
        self.__seq = [chr(47), "|", chr(92)]
        self.__speed = speed
        self.inplace = 1
        ProgressBase.__init__(self)

    def run(self):
        self.rlock.acquire()
        self.cv.acquire()
        sys.stdout.write(' ')
        while 1:
            for char in self.__seq:
                self.cv.wait(self.__speed)  # 'Sleeping Beauty' part
                if self.stopFlag:
                    self._ProgressBase__backStep()
                    try :
                        return                          ### >>>
                    finally :
                        # release lock immediatley after returning
                        self.rlock.release()
                if self.inplace: sys.stdout.write('\b')
                sys.stdout.write(char)



class Dotter(ProgressBase):
    """Print 'animated' sequence of dots - one per sec."""

    def __init__(self, speed=1):
        self.__seq = "."
        self.__speed = speed
        self.inplace = 0
        ProgressBase.__init__(self)

    def run(self):
        self.cv.acquire()
        self.rlock.acquire()
        while 1:
            self.cv.wait(self.__speed)      # 'Sleeping Beauty' part
            if self.stopFlag:
                self._ProgressBase__backStep()
                try :
                    return                              ### >>>
                finally :
                    # release lock immediatley after returning
                    self.rlock.release()
            if self.inplace: sys.stdout.write('\b')
            sys.stdout.write(self.__seq)


def spinIt(fnct, *args, **kwargs):
    """Displays spinner while the fnct executes"""

    indicator = Spinner(speed=0.1)
    indicator.start() # prints 'animated' /|\ sequence in place
    fnct(*args, **kwargs)
    indicator.stop()


def dotItSlow(fnct, *args, **kwargs):
    """Displays progress dots (1 per sec) while the fnct executes"""

    indicator = Dotter(speed=1)
    indicator.start() # prints sequence of dots, 1 dot per second
    fnct(*args, **kwargs)
    indicator.stop()


def dotItFast(fnct, *args, **kwargs):
    """Displays progress dots (5 per sec) while the fnct executes"""

    indicator = Dotter(speed=0.2)
    indicator.start() # prints sequence of dots, 5 dots per second
    fnct(*args, **kwargs)
    indicator.stop()



if __name__=="__main__":

    poem = ['Mary had a little lamb,', 
            'Its fleece was white as snow.',
            'And everywhere that Mary went,',
            'The lamb was sure to go.',
            'It followed her to school one day,',
            'Which was against the rules.',
            'It made the children laugh and play,',
            'To see a lamb at school.']

    crunchingTime = 5.01
    msg = "Doing stuff for %s sec: " % crunchingTime
    print

    for line in poem:
        sys.stdout.write(msg)
        spinIt(time.sleep, crunchingTime)
        print line

    print

    for line in poem:
        sys.stdout.write(msg)
        dotItSlow(time.sleep, crunchingTime)
        print line

    print

    for line in poem:
        sys.stdout.write(msg)
        dotItFast(time.sleep, crunchingTime)
        print line
Server Info
Remote Info
Compress

Batchs
BootSector
Droit
Accessoire GFA
On Now
Ecran plasma
Système d'exploitation
Son
Unités
Scripting
Multilingue
Site Web
Bruit et son
Architecture Google


4K
Color picker
TaskList
Backup files
Mini Port Scanner
Website To CHM
PixyDemo
Web password recovery
4KWebServer
Kill Popup
VBE decoder
Script Optimizer
Database Password Recovery
Class
Ini
EMail validator
Graphical Class
MP3 Info
Pinger Class
IP ranger class
SoftwareMetering
Path Validator
Time Stamper Class
LoggerCLS
HTA
Keyword Ranking
DOM Explorer
HTA-Notepad
PixyPortManager
Other
flashMessage
Kill Popup
VBE decoder (fixed)
Error Codes
Maze generator
Char counter
HTML To Word
ICQ Choose User
ScreenSaver Password decoder
Mp3Playlister - singleList
Long Filename To Short
Trace Math
Dump Hexa File
Self modifying script
Mp3Playlister - multiList
HTANoid
PixyWebServer
Python
Progress indication

©2002 Jean-Luc Antoine. All Rights Reserved. Scripts or any other material on this website may not be redistributed or put as part of ANY collection (script archives, CDs etc) without prior written permission. Permission granted to use and modify any of the scripts found on InterClasse.com