Python Progress Bar

Wie verwende ich einen Fortschrittsbalken, wenn mein Skript eine Aufgabe macht, die wahrscheinlich Zeit braucht?

Zum Beispiel, eine Funktion, die einige Zeit in Anspruch nimmt und zurückgibt True wenn getan. Wie kann ich während der Zeit, in der die Funktion ausgeführt wird, einen Fortschrittsbalken anzeigen?

Beachten Sie, dass ich das in Echtzeit braucht, also kann ich nicht herausfinden, was ich dagegen tun soll. Brauche ich dafür einen thread ? Ich habe keine Ahnung.

Im Moment drucke ich überhaupt nichts, während die Funktion ausgeführt wird, aber ein Fortschrittsbalken wäre schön. Auch ich bin mehr daran interessiert, wie dies aus einer Code-Sicht getan werden kann.

14 Solutions collect form web for “Python Progress Bar”

Es gibt spezifische Bibliotheken ( wie diese hier ), aber vielleicht etwas ganz einfaches tun würde:

 import time import sys toolbar_width = 40 # setup toolbar sys.stdout.write("[%s]" % (" " * toolbar_width)) sys.stdout.flush() sys.stdout.write("\b" * (toolbar_width+1)) # return to start of line, after '[' for i in xrange(toolbar_width): time.sleep(0.1) # do real work here # update the bar sys.stdout.write("-") sys.stdout.flush() sys.stdout.write("\n") 

Anmerkung: Diese Fortschrittsleiste ist eine Gabel von Fortschrittsbalken, die in Jahren nicht gepflegt wurde.

Mit tqdm kannst du einen Fortschrittszähler zu deiner Schleife in einer Sekunde hinzufügen:

 In [20]: import time In [21]: from tqdm import * In [23]: for i in tqdm(range(10)): ....: time.sleep(3) 60%|██████ | 6/10 [00:18<00:12, 0.33 it/s] 

Die obigen Vorschläge sind ziemlich gut, aber ich denke, die meisten Leute wollen einfach nur eine fertige Lösung, ohne Abhängigkeiten von externen Paketen, aber auch wiederverwendbar.

Ich habe die besten Punkte von allen oben, und machte es in eine Funktion, zusammen mit einem Test Fällen.

Um es zu benutzen, kopiere einfach die Zeilen unter "def update_progress (Fortschritt)" aber nicht das Test-Skript. Vergessen Sie nicht, Sys zu importieren. Nennen Sie dies, wann immer Sie die Fortschrittsleiste anzeigen oder aktualisieren müssen.

Dies funktioniert durch direktes Senden der "\ r" -Symbol zu Konsole, um den Cursor zurück zum Anfang zu bewegen. "Print" in python nicht rekurrieren das obige symbol für diesen zweck, daher brauchen wir 'sys'

 import time, sys # update_progress() : Displays or updates a console progress bar ## Accepts a float between 0 and 1. Any int will be converted to a float. ## A value under 0 represents a 'halt'. ## A value at 1 or bigger represents 100% def update_progress(progress): barLength = 10 # Modify this to change the length of the progress bar status = "" if isinstance(progress, int): progress = float(progress) if not isinstance(progress, float): progress = 0 status = "error: progress var must be float\r\n" if progress < 0: progress = 0 status = "Halt...\r\n" if progress >= 1: progress = 1 status = "Done...\r\n" block = int(round(barLength*progress)) text = "\rPercent: [{0}] {1}% {2}".format( "#"*block + "-"*(barLength-block), progress*100, status) sys.stdout.write(text) sys.stdout.flush() # update_progress test script print "progress : 'hello'" update_progress("hello") time.sleep(1) print "progress : 3" update_progress(3) time.sleep(1) print "progress : [23]" update_progress([23]) time.sleep(1) print "" print "progress : -10" update_progress(-10) time.sleep(2) print "" print "progress : 10" update_progress(10) time.sleep(2) print "" print "progress : 0->1" for i in range(100): time.sleep(0.1) update_progress(i/100.0) print "" print "Test completed" time.sleep(10) 

Dies ist, was das Ergebnis des Testskripts zeigt (der letzte Fortschrittsbalken animiert):

 progress : 'hello' Percent: [----------] 0% error: progress var must be float progress : 3 Percent: [##########] 100% Done... progress : [23] Percent: [----------] 0% error: progress var must be float progress : -10 Percent: [----------] 0% Halt... progress : 10 Percent: [##########] 100% Done... progress : 0->1 Percent: [##########] 99.0% Test completed 

Für eine ähnliche Anwendung (die Verfolgung der Fortschritte in einer Schleife) Ich habe einfach die Python-Fortschrittsbalance verwendet :

Ihr Beispiel geht so etwas,

 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 

Ich habe gerade eine einfache Fortschrittsklasse für meine Bedürfnisse gemacht, nachdem ich hier nach einer gleichwertigen Lösung gesucht habe. Ich hart, ich könnte es gut machen.

 from __future__ import print_function import sys import re class ProgressBar(object): DEFAULT = 'Progress: %(bar)s %(percent)3d%%' FULL = '%(bar)s %(current)d/%(total)d (%(percent)3d%%) %(remaining)d to go' def __init__(self, total, width=40, fmt=DEFAULT, symbol='=', output=sys.stderr): assert len(symbol) == 1 self.total = total self.width = width self.symbol = symbol self.output = output self.fmt = re.sub(r'(?P<name>%\(.+?\))d', r'\g<name>%dd' % len(str(total)), fmt) self.current = 0 def __call__(self): percent = self.current / float(self.total) size = int(self.width * percent) remaining = self.total - self.current bar = '[' + self.symbol * size + ' ' * (self.width - size) + ']' args = { 'total': self.total, 'bar': bar, 'current': self.current, 'percent': percent * 100, 'remaining': remaining } print('\r' + self.fmt % args, file=self.output, end='') def done(self): self.current = self.total self() print('', file=self.output) 

Beispiel:

 from time import sleep progress = ProgressBar(80, fmt=ProgressBar.FULL) for x in xrange(progress.total): progress.current += 1 progress() sleep(0.1) progress.done() 

Wird ausdrucken:

[======== ] 17/80 ( 21%) 63 to go

Versuche den Fortschritt von https://pypi.python.org/pypi/progress .

 from progress.bar import Bar bar = Bar('Processing', max=20) for i in range(20): # Do some work bar.next() bar.finish() 

Das Ergebnis wird eine Bar wie die folgenden:

 Processing |############# | 42/100 

Ich mag die Python-Fortschritte , da es sehr einfach zu bedienen ist.

Für den einfachsten Fall ist es nur:

 import progressbar import time progress = progressbar.ProgressBar() for i in progress(range(80)): time.sleep(0.01) 

Das Aussehen kann angepasst werden und es kann die geschätzte Restzeit anzeigen. Für ein Beispiel den gleichen Code wie oben verwenden, aber mit:

 progress = progressbar.ProgressBar(widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage(), ' ', progressbar.ETA()]) 

Verwenden Sie diese Bibliothek: fish ( GitHub ).

Verwendung:

 >>> import fish >>> while churning: ... churn_churn() ... fish.animate() 

Habe Spaß!

Viele der Antworten oben verlassen sich auf externe Pakete, aber ich denke auch (wie einige oben angegeben), dass die meisten Menschen nur eine fertige Lösung wollen. Der Code unten kann an Ihre Bedürfnisse angepasst werden, indem Sie den String Teil anpassen.

Es ist einfacher und funktioniert ohne die Notwendigkeit eines zweiten Threads, um die Bar zu aktualisieren. Einige Pakete oben tun das. Ein zweiter Thread kann zum Beispiel für ein ipython Notebook ein Problem sein.

Der Code bellow funktioniert nur mit Iteratoren, die eine Länge liefern (dh len (Iterator) muss definiert werden).

 import sys def progressbar(it, prefix="", size=60): count = len(it) def _show(_i): x = int(size*_i/count) sys.stdout.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), _i, count)) sys.stdout.flush() _show(0) for i, item in enumerate(it): yield item _show(i+1) sys.stdout.write("\n") sys.stdout.flush() 

Beispiel:

 import time for i in progressbar(range(15), "Computing: ", 40): time.sleep(0.1) # any calculation you need 

Ausgabe:

 Computing: [........................................] 0/15 

 Computing: [########................................] 3/15 

 Computing: [########################################] 15/15 

it kann ein beliebiges, mit einem len zerlegbares Objekt sein, zB ['a', 'b', 'c'] 'funktioniert ganz gut.

Wenn deine Arbeit nicht in messbare Stücke zerlegt werden kann, kannst du deine Funktion in einem neuen Thread aufrufen und wie lange es dauert:

 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" 

Sie können die Timing-Präzision nach Bedarf deutlich erhöhen.

Hier ist eine kurze Lösung, die die Ladeleiste programmgesteuert baut (Sie müssen entscheiden, wie lange Sie es wollen).

 import time n = 33 # or however many loading slots you want to have load = 0.01 # artificial loading time! loading = '.' * n # for strings, * is the repeat operator for i in range(n+1): # this loop replaces each dot with a hash! print('\r%s Loading at %3d percent!' % (loading, i*100/n), end='') loading = loading[:i] + '#' + loading[i+1:] time.sleep(load) 

Ich mag diese Seite .

Startet mit einfachem Beispiel und bewegt sich auf eine Multi-Thread-Version. Arbeitet aus der Schachtel. Keine Drittpaketpakete erforderlich.

Der Code sieht so aus:

 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) 

Oder hier ist das Beispiel, um Threads zu verwenden, um die Spinning-Ladeleiste laufen zu lassen, während das Programm läuft:

 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 

Du solltest den Fortschrittsbalken mit der Aufgabe verknüpfen (damit der Fortschritt: D). Zum Beispiel, wenn Sie FTPing eine Datei sind, können Sie ftplib sagen, um eine bestimmte Größe Puffer zu greifen, sagen wir, 128K, und dann fügen Sie zu Ihrem Fortschrittsbalken, was Prozentsatz der Dateigröße 128k darstellt. Wenn Sie die CLI verwenden und Ihr Fortschrittszähler 20 Zeichen lang ist, würden Sie ein Zeichen hinzufügen, wenn 1/20 der Datei übertragen wurde.

@Massagran: Es funktioniert gut in meinen Programmen. Außerdem müssen wir einen Zähler hinzufügen, um die Schleifenzeiten anzuzeigen. Dieser Zähler spielt als Argument der Methodenaktualisierung. Zum Beispiel: lese alle Zeilen einer Testdatei und behandle sie auf etwas. Angenommen, die Funktion dosth() betrifft nicht die Variable i .

 lines = open(sys.argv[1]).readlines() i = 0 widgets=[Percentage(), Bar()] pbar = ProgressBar(widgets=widgets,maxval=len(lines)).start() pbar.start() for line in lines:<pre> dosth(); i += 1 pbar.update(i)</pre> pbar.finish() 

Die Variable i steuert den Status von pbar über die Methodenaktualisierung

Python ist die beste Programmiersprache der Welt.