Python Progress Bar

后端 未结 30 2220
礼貌的吻别
礼貌的吻别 2020-11-22 06:13

How do I use a progress bar when my script is doing some task that is likely to take time?

For example, a function which takes some time to complete and returns

相关标签:
30条回答
  • 2020-11-22 07:10

    for a similar application (keeping track of the progress in a loop) I simply used the python-progressbar:

    Their example goes something like this,

    from progressbar import *               # just a simple progress bar
    
    
    widgets = ['Test: ', Percentage(), ' ', Bar(marker='0',left='[',right=']'),
               ' ', ETA(), ' ', FileTransferSpeed()] #see docs for other options
    
    pbar = ProgressBar(widgets=widgets, maxval=500)
    pbar.start()
    
    for i in range(100,500+1,50):
        # here do something long at each iteration
        pbar.update(i) #this adds a little symbol at each iteration
    pbar.finish()
    print
    
    0 讨论(0)
  • 2020-11-22 07:10

    I like Brian Khuu's answer for its simplicity and not needing external packages. I changed it a bit so I'm adding my version here:

    import sys
    import time
    
    
    def updt(total, progress):
        """
        Displays or updates a console progress bar.
    
        Original source: https://stackoverflow.com/a/15860757/1391441
        """
        barLength, status = 20, ""
        progress = float(progress) / float(total)
        if progress >= 1.:
            progress, status = 1, "\r\n"
        block = int(round(barLength * progress))
        text = "\r[{}] {:.0f}% {}".format(
            "#" * block + "-" * (barLength - block), round(progress * 100, 0),
            status)
        sys.stdout.write(text)
        sys.stdout.flush()
    
    
    runs = 300
    for run_num in range(runs):
        time.sleep(.1)
        updt(runs, run_num + 1)
    

    It takes the total number of runs (total) and the number of runs processed so far (progress) assuming total >= progress. The result looks like this:

    [#####---------------] 27%
    
    0 讨论(0)
  • 2020-11-22 07:10

    I like this page.

    Starts with simple example and moves onto a multi-threaded version. Works out of the box. No 3rd party packages required.

    The code will look something like this:

    import time
    import sys
    
    def do_task():
        time.sleep(1)
    
    def example_1(n):
        for i in range(n):
            do_task()
            print '\b.',
            sys.stdout.flush()
        print ' Done!'
    
    print 'Starting ',
    example_1(10)
    

    Or here is example to use threads in order to run the spinning loading bar while the program is running:

    import sys
    import time
    import threading
    
    class progress_bar_loading(threading.Thread):
    
        def run(self):
                global stop
                global kill
                print 'Loading....  ',
                sys.stdout.flush()
                i = 0
                while stop != True:
                        if (i%4) == 0: 
                            sys.stdout.write('\b/')
                        elif (i%4) == 1: 
                            sys.stdout.write('\b-')
                        elif (i%4) == 2: 
                            sys.stdout.write('\b\\')
                        elif (i%4) == 3: 
                            sys.stdout.write('\b|')
    
                        sys.stdout.flush()
                        time.sleep(0.2)
                        i+=1
    
                if kill == True: 
                    print '\b\b\b\b ABORT!',
                else: 
                    print '\b\b done!',
    
    
    kill = False      
    stop = False
    p = progress_bar_loading()
    p.start()
    
    try:
        #anything you want to run. 
        time.sleep(1)
        stop = True
    except KeyboardInterrupt or EOFError:
             kill = True
             stop = True
    
    0 讨论(0)
  • 2020-11-22 07:10

    This is my simple solution:

    import time
    
    def progress(_cur, _max):
        p = round(100*_cur/_max)
        b = f"Progress: {p}% - ["+"."*int(p/5)+" "*(20-int(p/5))+"]"
        print(b, end="\r")
    
    # USAGE:
    for i in range(0,101):
        time.sleep(0.1) 
        progress(i,100)
    
    print("..."*5, end="\r")
    print("Done")
    
    0 讨论(0)
  • 2020-11-22 07:14

    You should link the progress bar to the task at hand (so that it measures the progress :D). For example, if you are FTPing a file, you can tell ftplib to grab a certain size buffer, let's say 128K, and then you add to your progress bar whatever percentage of the filesize 128k represents. If you are using the CLI, and your progress meter is 20 characters long, you would add one character when 1/20th of the file had transferred.

    0 讨论(0)
  • 2020-11-22 07:15

    If your work can't be broken down into measurable chunks, you could call your function in a new thread and time how long it takes:

    import thread
    import time
    import sys
    
    def work():
        time.sleep( 5 )
    
    def locked_call( func, lock ):
        lock.acquire()
        func()
        lock.release()
    
    lock = thread.allocate_lock()
    thread.start_new_thread( locked_call, ( work, lock, ) )
    
    # This part is icky...
    while( not lock.locked() ):
        time.sleep( 0.1 )
    
    while( lock.locked() ):
        sys.stdout.write( "*" )
        sys.stdout.flush()
        time.sleep( 1 )
    print "\nWork Done"
    

    You can obviously increase the timing precision as required.

    0 讨论(0)
提交回复
热议问题