Python-Fortschrittsbalken

307

Wie verwende ich einen Fortschrittsbalken, wenn mein Skript eine Aufgabe ausführt, die wahrscheinlich einige Zeit in Anspruch nimmt?

Zum Beispiel eine Funktion, deren Ausführung einige Zeit in Anspruch nimmt und die nach Abschluss zurückgegeben Truewird. Wie kann ich während der Ausführung der Funktion einen Fortschrittsbalken anzeigen?

Beachten Sie, dass dies in Echtzeit erfolgen muss, damit ich nicht herausfinden kann, was ich dagegen tun soll. Benötige ich eine threaddafür? Ich habe keine Ahnung.

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

user225312
quelle
Verwenden Sie nur ein GUI-Toolkit oder eine CLI?
Bobby
CLI. Aber ich kann eine Drittanbieter-Bibliothek verwenden, das ist kein Problem. Mit GUI kann ich das tun, aber ich war am CLI-Teil interessiert.
user225312
1
Mögliches Duplikat der Textfortschrittsleiste in der Konsole Beachten Sie, dass diese Frage zwar drei Tage zuvor veröffentlicht wurde, die verknüpfte Frage jedoch häufiger angezeigt wird.
Greenstick
Hier ist eine Lösung für ein Jupyter-Notizbuch: mikulskibartosz.name/…
Steven C. Howell
Ich habe eine neue Art von Fortschrittsbalken veröffentlicht, die Sie drucken, Durchsatz und Eta anzeigen und sogar pausieren können, abgesehen von den sehr coolen Animationen! Bitte werfen Sie einen Blick darauf: github.com/rsalmei/alive-progress ! lebendiger Fortschritt
rsalmei

Antworten:

185

Es gibt bestimmte Bibliotheken ( wie diese hier ), aber vielleicht würde etwas sehr Einfaches tun:

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") # this ends the progress bar

Hinweis: progressbar2 ist eine Abzweigung von progressbar, die seit Jahren nicht mehr gewartet wurde.

ChristopheD
quelle
14
Dies skaliert nicht für viele Schritte ... pypi.python.org/pypi/progress ist viel einfacher zu bedienen
m13r
5
Ich habe diesen Code ausprobiert und er hat einen NameError: name 'xrange' is not definedFehler ausgelöst. Vermisse ich ein Modul?
Pilzmann
6
@ GokuMcSpock9733 Welche Version von Python verwenden Sie? Pythons 2 xrangeist Pythons 3 range.
Quapka
9
Dies sollte nicht die beste Antwort sein. Die andere Antwort (mit tqdm) ist zumindest für mich viel besser.
Florian
1
Fortschrittsbalken der Armen in Python 3:print('■', end='', flush=True)
PatrickT
351

Mit tqdm können Sie Ihren Loops in Sekundenschnelle eine Fortschrittsanzeige hinzufügen:

In [1]: import time

In [2]: from tqdm import tqdm

In [3]: for i in tqdm(range(10)):
   ....:     time.sleep(3)

 60%|██████    | 6/10 [00:18<00:12,  0.33 it/s]

Außerdem gibt es eine grafische Version von tqdm seit v2.0.0( d977a0c):

In [1]: import time

In [2]: from tqdm import tqdm_gui

In [3]: for i in tqdm_gui(range(100)):
  ....:     time.sleep(3)

tqdm GUI-Fenster

Aber seien Sie vorsichtig, da a ausgelöst werden tqdm_guikann, TqdmExperimentalWarning: GUI is experimental/alphakönnen Sie es mit verwenden warnings.simplefilter("ignore"), aber danach werden alle Warnungen in Ihrem Code ignoriert.

scls
quelle
9
Dies ist die einzige Lösung, die ich gefunden habe, um mit Terminal, qtconsole und Notebook zu arbeiten
Ivelin
3
Funktioniert es mit einem iterablen? Ich hatte Probleme, es mit einer Liste von Zeichenfolgen zum Laufen zu bringen.
Josh Usre
3
@JoshUsre Ja, es sollte mit jedem Iterable funktionieren, für den Moment habe ich kein Iterable gesehen, an dem es erstickt ist. Für die Anzeige der ETA (verbleibende Zeit) muss die Iterable jedoch über eine __len__Eigenschaft verfügen, oder der Benutzer muss das totalArgument angeben tqdm. Andernfalls funktioniert die Bar, jedoch ohne ETA.
gaborous
6
@gaborous: Wieso ist dies nicht die am besten gewählte Antwort? Diese einfache Lösung funktioniert im Gegensatz zur Top-Antwort sowohl im Terminal als auch im Jupyter-Notebook.
Ébe Isaac
6
zum laufen in einem jupyter notebook verwenden from tqdm import tqdm_notebook as tqdm. Sonst schreibt es nicht in eine Zeile.
Jacques MALAPRADE
81

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

Ich habe die besten Punkte von all dem bekommen und es zusammen mit einem Testfall zu einer Funktion gemacht.

Um es zu verwenden, kopieren Sie einfach die Zeilen unter "def update_progress (progress)", aber nicht das Testskript. Vergessen Sie nicht, sys zu importieren. Rufen Sie dies auf, wenn Sie den Fortschrittsbalken anzeigen oder aktualisieren müssen.

Dies funktioniert, indem das Symbol "\ r" direkt an die Konsole gesendet wird, um den Cursor zurück zum Start zu bewegen. "print" in Python erkennt das obige Symbol für diesen Zweck nicht neu, daher benötigen 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(101):
    time.sleep(0.1)
    update_progress(i/100.0)

print ""
print "Test completed"
time.sleep(10)

Das Ergebnis des Testskripts zeigt Folgendes (der letzte Fortschrittsbalken wird 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: [##########] 100% Done...
Test completed
Brian Khuu
quelle
10
Der animierte Test (letzter) sollte in range(101)nicht 100 sagen , der Fortschritt stoppt bei 99% und wird nie angezeigt.
Nick Humrich
41

Diese Antwort basiert nicht auf externen Paketen . Ich denke auch, dass die meisten Leute nur einen vorgefertigten Code wollen . Der folgende Code kann durch Anpassen an Ihre Bedürfnisse angepasst werden: Balkenfortschrittssymbol '#', Balken size, Text prefixusw.

import sys

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

Verwendungszweck:

import time

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

Ausgabe:

Computing: [################........................] 4/15
  • Benötigt keinen zweiten Thread . Einige der oben genannten Lösungen / Pakete erfordern. Ein zweiter Thread kann beispielsweise ein Problem sein jupyter notebook.

  • Funktioniert mit jedem iterierbaren Element. Es bedeutet alles, len()was verwendet werden kann. A list, a dictvon irgendetwas zum Beispiel['a', 'b', 'c' ... 'g']

Sie können auch die Ausgabe von Datei auf sich ändernde ändern sys.stderrzum Beispiel

eusoubrasileiro
quelle
Ich mag diese Lösung, Generatoren werden den folgenden Fehler werfen:TypeError: object of type 'generator' has no len()
Jabellcu
@jabellcu in diesem Fall ( generators) müssen Sie es mit einem umschließen list(). Gefällt for i in progressbar(list(your_generator), "Computing: ", 40):
mir
22

Für eine ähnliche Anwendung (Verfolgen des Fortschritts in einer Schleife) habe ich einfach die Python-Fortschrittsleiste verwendet :

Ihr Beispiel lautet ungefähr so:

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
Massagran
quelle
3
Versuchen Sie aus progressbar2Gründen der Python 3-Kompatibilität das Paket. Der obige Code funktioniert damit.
d33tah
2
Hast du wirklich gerade benutzt import *?
Eric
20

Versuchen Sie den Fortschritt unter 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 ist ein Balken wie der folgende:

Processing |#############                   | 42/100
Vladislav
quelle
Hab es gerade versucht. Sehr einfach zu bedienen. Ich brauchte ungefähr 2 Minuten (einschließlich des Fortschritts der Pip-Installation), um eine Statusleiste zum Laufen zu bringen.
Perelin
progressmacht schöne Balken, aber es schlägt fehl, wenn andere Software manipuliert stderr. Entschuldigung, aber ich habe das genaue Problem nicht untersucht.
Arthur
Es wird eine Zeile für jeden Fortschritt in meiner Ubuntu-Konsole gedruckt. Wenn beispielsweise max = 20, werden 20 Zeilen gedruckt ... Wie kann ich dafür sorgen, dass nur eine Zeile gedruckt wird?
L's World
19

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

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()

Druckt Folgendes:

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

Romuald Brunet
quelle
3
Super, danke dafür. Übrigens können Sie das progress.currentInkrementieren am Ende von hinzufügen __call__, um die Interaktion mit dem Objekt aus dem Hauptcode noch weiter einzuschränken.
Npit
Dieser Code ist einfach, präzise und nützlich! Danke dir!
Ian Rehwinkel
15

Ich mag Brian Khuus Antwort wegen seiner Einfachheit und weil ich keine externen Pakete benötige. Ich habe es ein wenig geändert, also füge ich hier meine Version hinzu:

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)

Es wird die Gesamtzahl der Läufe ( total) und die Anzahl der bisher verarbeiteten Läufe ( progress) angenommen total >= progress. Das Ergebnis sieht folgendermaßen aus:

[#####---------------] 27%
Gabriel
quelle
14

Sie können tqdm verwenden :

from tqdm import tqdm

with tqdm(total=100, desc="Adding Users", bar_format="{l_bar}{bar} [ time left: {remaining} ]") as pbar:
    for i in range(100):
        time.sleep(3)
        pbar.update(1)

In diesem Beispiel läuft der Fortschrittsbalken 5 Minuten lang und wird folgendermaßen angezeigt:

Adding Users:   3%|█████▊                                     [ time left: 04:51 ]                                                                                                        

Sie können es ändern und anpassen, wie Sie möchten.

Eyal.D
quelle
11

Um ein Fortschrittsbalken-Framework auf nützliche Weise zu verwenden, dh um einen tatsächlichen Fortschrittsprozentsatz und eine geschätzte ETA zu erhalten, müssen Sie in der Lage sein, anzugeben, wie viele Schritte es haben wird.

Können Sie Ihre Rechenfunktion in einem anderen Thread in mehrere logische Schritte aufteilen? Können Sie den Code ändern?

Sie müssen es nicht umgestalten oder in tatsächliche Methoden aufteilen, Sie können einfach einige strategische yields an einigen Stellen darin platzieren! Wenn die teure Funktion eine for-Schleife hat , fügen Sie einfach eine ein. Sie sollten erst am Ende wissen, wie viel Ertrag erzielt wird, um die besten Ergebnisse zu erzielen.

Auf diese Weise könnte Ihre Funktion ungefähr so ​​aussehen:

def compute():
    time.sleep(1)  # some processing here
    yield  # insert these
    time.sleep(1)
    yield
    time.sleep(1)
    yield

oder dieses:

def compute():
    for i in range(1000):
        time.sleep(.1)  # some processing here
        yield  # insert these

Mit dieser Art von Funktion können Sie Folgendes installieren:

pip install alive-progress

Und benutze es wie:

from alive_progress import alive_bar

with alive_bar(3) as bar:  # or a 1000 in the loop example.
    for i in compute():
        bar()

Um einen coolen Fortschrittsbalken zu bekommen!

|█████████████▎                          | ▅▃▁ 1/3 [33%] in 1s (1.0/s, eta: 2s)

Haftungsausschluss: Ich bin der Autor von living_progress, aber es sollte Ihr Problem gut lösen. Lesen Sie die Dokumentation unter https://github.com/rsalmei/alive-progress . Hier ist ein Beispiel dafür, was es kann:

lebendiger Fortschritt

rsalmei
quelle
8

Ich mag die Python-Fortschrittsleiste sehr , da sie 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 Erscheinungsbild kann angepasst werden und die geschätzte verbleibende Zeit anzeigen. Verwenden Sie für ein Beispiel denselben Code wie oben, jedoch mit:

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

Wenn es sich um eine große Schleife mit einer festgelegten Anzahl von Iterationen handelt, die viel Zeit in Anspruch nimmt, können Sie diese von mir erstellte Funktion verwenden. Jede Iteration der Schleife fügt den Fortschritt hinzu. Wenn count die aktuelle Iteration der Schleife ist, ist total der Wert, zu dem Sie eine Schleife ausführen, und size (int) gibt an, wie groß der Balken in Schritten von 10 sein soll, dh (Größe 1 = 10 Zeichen, Größe 2 = 20 Zeichen).

import sys
def loadingBar(count,total,size):
    percent = float(count)/float(total)*100
    sys.stdout.write("\r" + str(int(count)).rjust(3,'0')+"/"+str(int(total)).rjust(3,'0') + ' [' + '='*int(percent/10)*size + ' '*(10-int(percent/10))*size + ']')

Beispiel:

for i in range(0,100):
     loadingBar(i,100,2)
     #do some code 

Ausgabe:

i = 50
>> 050/100 [==========          ]
jelde015
quelle
4

Verwenden Sie diese Bibliothek: fish( GitHub ).

Verwendungszweck:

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

Habe Spaß!

Etienne
quelle
Es ist möglich. Sie sollten den Entwickler fragen oder das Ticket hinterlassen: github.com/lericson/fish .
Etienne
4

Der folgende Code ist eine recht allgemeine Lösung und enthält auch eine Schätzung der verstrichenen Zeit und der verbleibenden Zeit. Sie können jedes iterable damit verwenden. Der Fortschrittsbalken hat eine feste Größe von 25 Zeichen, kann jedoch Aktualisierungen in Schritten von 1% mit Voll-, Halb- und Viertelblockzeichen anzeigen. Die Ausgabe sieht folgendermaßen aus:

 18% |████▌                    | \ [0:00:01, 0:00:06]

Code mit Beispiel:

import sys, time
from numpy import linspace

def ProgressBar(iterObj):
  def SecToStr(sec):
    m, s = divmod(sec, 60)
    h, m = divmod(m, 60)
    return u'%d:%02d:%02d'%(h, m, s)
  L = len(iterObj)
  steps = {int(x):y for x,y in zip(linspace(0, L, min(100,L), endpoint=False),
                                   linspace(0, 100, min(100,L), endpoint=False))}
  qSteps = ['', u'\u258E', u'\u258C', u'\u258A'] # quarter and half block chars
  startT = time.time()
  timeStr = '   [0:00:00, -:--:--]'
  activity = [' -',' \\',' |',' /']
  for nn,item in enumerate(iterObj):
    if nn in steps:
      done = u'\u2588'*int(steps[nn]/4.0)+qSteps[int(steps[nn]%4)]
      todo = ' '*(25-len(done))
      barStr = u'%4d%% |%s%s|'%(steps[nn], done, todo)
    if nn>0:
      endT = time.time()
      timeStr = ' [%s, %s]'%(SecToStr(endT-startT),
                             SecToStr((endT-startT)*(L/float(nn)-1)))
    sys.stdout.write('\r'+barStr+activity[nn%4]+timeStr); sys.stdout.flush()
    yield item
  barStr = u'%4d%% |%s|'%(100, u'\u2588'*25)
  timeStr = '   [%s, 0:00:00]\n'%(SecToStr(time.time()-startT))
  sys.stdout.write('\r'+barStr+timeStr); sys.stdout.flush()

# Example
s = ''
for c in ProgressBar(list('Disassemble and reassemble this string')):
  time.sleep(0.2)
  s += c
print(s)

Verbesserungsvorschläge oder andere Kommentare sind willkommen. Prost!

Niko
quelle
3

Ich mag diese Seite .

Beginnt mit einem einfachen Beispiel und wechselt zu einer Multithread-Version. Funktioniert sofort. Keine Pakete von Drittanbietern erforderlich.

Der Code sieht ungefähr 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 ein Beispiel für die Verwendung von Threads, um die sich drehende Ladeleiste auszuführen, während das Programm ausgeführt wird:

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
user1862895
quelle
3

In Python3 ist das ganz einfach:

   import time
   import math

    def show_progress_bar(bar_length, completed, total):
        bar_length_unit_value = (total / bar_length)
        completed_bar_part = math.ceil(completed / bar_length_unit_value)
        progress = "*" * completed_bar_part
        remaining = " " * (bar_length - completed_bar_part)
        percent_done = "%.2f" % ((completed / total) * 100)
        print(f'[{progress}{remaining}] {percent_done}%', end='\r')

    bar_length = 30
    total = 100
    for i in range(0, total + 1):
        show_progress_bar(bar_length, i, total)
        time.sleep(0.1)

    print('\n')
Anton Ivanov
quelle
3

Bei der Ausführung in Jupyter-Notebooks funktioniert die Verwendung von normalem tqdm nicht, da die Ausgabe in mehreren Zeilen geschrieben wird. Verwenden Sie stattdessen Folgendes:

import time
from tqdm import tqdm_notebook as tqdm

for i in tqdm(range(100))
    time.sleep(0.5)
Jacques MALAPRADE
quelle
2

Wenn Ihre Arbeit nicht in messbare Teile zerlegt werden kann, können Sie Ihre Funktion in einem neuen Thread aufrufen und festlegen, 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 natürlich die Timing-Genauigkeit nach Bedarf erhöhen.

bvanvugt
quelle
Wo würde man die Arbeit machen, die im Code als Antwort gemessen werden soll?
unseen_rider
2

Ich mag Gabriels Antwort, aber ich habe sie geändert, um flexibel zu sein. Sie können die Balkenlänge an die Funktion senden und Ihren Fortschrittsbalken mit einer beliebigen Länge abrufen. Und Sie können keinen Fortschrittsbalken mit null oder negativer Länge haben. Sie können diese Funktion auch wie Gabriels Antwort verwenden (siehe Beispiel 2).

import sys
import time

def ProgressBar(Total, Progress, BarLength=20, ProgressIcon="#", BarIcon="-"):
    try:
        # You can't have a progress bar with zero or negative length.
        if BarLength <1:
            BarLength = 20
        # Use status variable for going to the next line after progress completion.
        Status = ""
        # Calcuting progress between 0 and 1 for percentage.
        Progress = float(Progress) / float(Total)
        # Doing this conditions at final progressing.
        if Progress >= 1.:
            Progress = 1
            Status = "\r\n"    # Going to the next line
        # Calculating how many places should be filled
        Block = int(round(BarLength * Progress))
        # Show this
        Bar = "[{}] {:.0f}% {}".format(ProgressIcon * Block + BarIcon * (BarLength - Block), round(Progress * 100, 0), Status)
        return Bar
    except:
        return "ERROR"

def ShowBar(Bar):
    sys.stdout.write(Bar)
    sys.stdout.flush()

if __name__ == '__main__':
    print("This is a simple progress bar.\n")

    # Example #1:
    print('Example #1')
    Runs = 10
    for i in range(Runs + 1):
        progressBar = "\rProgress: " + ProgressBar(10, i, Runs)
        ShowBar(progressBar)
        time.sleep(1)

    # Example #2:
    print('\nExample #2')
    Runs = 10
    for i in range(Runs + 1):
        progressBar = "\rProgress: " + ProgressBar(10, i, 20, '|', '.')
        ShowBar(progressBar)
        time.sleep(1)

    print('\nDone.')

# Example #2:
Runs = 10
for i in range(Runs + 1):
    ProgressBar(10, i)
    time.sleep(1)

Ergebnis:

Dies ist ein einfacher Fortschrittsbalken.

Beispiel 1

Fortschritt: [### -------] 30%

Beispiel 2

Fortschritt: [||||||||||||| ........] 60%

Getan.

Saeed Zahedian Abroodi
quelle
2

Ich habe die format()Methode verwendet, um einen Lastbalken zu erstellen. Hier ist meine Lösung:

import time

loadbarwidth = 23

for i in range(1, loadbarwidth + 1):
    time.sleep(0.1) 

    strbarwidth = '[{}{}] - {}\r'.format(
        (i * '#'),
        ((loadbarwidth - i) * '-'),
        (('{:0.2f}'.format(((i) * (100/loadbarwidth))) + '%'))
    )

    print(strbarwidth ,end = '')

print()

Ausgabe:

[#######################] - 100.00%
Matheus Tavares
quelle
1

Hier ist eine kurze Lösung, mit der die Ladeleiste programmgesteuert erstellt wird (Sie müssen entscheiden, wie lange Sie möchten).

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)
étale-kohomologie
quelle
1

Versuchen Sie PyProg. PyProg ist eine Open-Source-Bibliothek für Python, mit der Sie super anpassbare Fortschrittsanzeigen und Balken erstellen können.

Es ist derzeit in Version 1.0.2; Es wird auf Github gehostet und ist auf PyPI verfügbar (Links unten). Es ist kompatibel mit Python 3 & 2 und kann auch mit Qt Console verwendet werden.

Es ist wirklich einfach zu bedienen. Der folgende Code:

import pyprog
from time import sleep

# Create Object
prog = pyprog.ProgressBar(" ", "", 34)
# Update Progress Bar
prog.update()

for i in range(34):
    # Do something
    sleep(0.1)
    # Set current status
    prog.set_stat(i + 1)
    # Update Progress Bar again
    prog.update()

# Make the Progress Bar final
prog.end()

wird herstellen:

Initial State:
Progress: 0% --------------------------------------------------

When half done:
Progress: 50% #########################-------------------------

Final State:
Progress: 100% ##################################################

Ich habe PyProg tatsächlich gemacht, weil ich eine einfache, aber super anpassbare Fortschrittsbalkenbibliothek brauchte. Sie können es einfach installieren mit : pip install pyprog.

PyProg Github: https://github.com/Bill13579/pyprog
PyPI: https://pypi.python.org/pypi/pyprog/

Bill Kudo
quelle
1

Sie können auch enlighten verwenden . Der Hauptvorteil ist, dass Sie gleichzeitig protokollieren können, ohne Ihren Fortschrittsbalken zu überschreiben.

import time
import enlighten

manager = enlighten.Manager()
pbar = manager.counter(total=100)

for num in range(1, 101):
    time.sleep(0.05)
    print('Step %d complete' % num)
    pbar.update()

Es werden auch mehrere Fortschrittsbalken verarbeitet.

import time
import enlighten

manager = enlighten.Manager()
odds = manager.counter(total=50)
evens = manager.counter(total=50)

for num in range(1, 101):
    time.sleep(0.05)
    if num % 2:
        odds.update()
    else:
        evens.update()
aviso
quelle
1

Verwenden Sie die Fortschrittsbibliothek !

pip install progress

Hier ist eine benutzerdefinierte Unterklasse, die ich geschrieben habe, um die ETA / Verstrichenen Zeiten in ein besser lesbares Format zu formatieren:

import datetime
from progress.bar import IncrementalBar


class ProgressBar(IncrementalBar):
    '''
    My custom progress bar that:
       - Show %, count, elapsed, eta
       - Time is shown in H:M:S format
    '''

    message = 'Progress'
    suffix  = '%(percent).1f%% (%(index)d/%(max)d) -- %(elapsed_min)s (eta: %(eta_min)s)'

    def formatTime(self, seconds):
        return str(datetime.timedelta(seconds=seconds))

    @property
    def elapsed_min(self):
        return self.formatTime(self.elapsed)

    @property
    def eta_min(self):
        return self.formatTime(self.eta)

if __name__=='__main__':
    counter = 120
    bar     = ProgressBar('Processing', max=counter)

    for i in range(counter):
        bar.next()
        time.sleep(1)

    bar.finish()
kakhkAtion
quelle
1

Das ist meine einfache Lösung:

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")
Machen, machen, machen
quelle
0

Sie sollten den Fortschrittsbalken mit der jeweiligen Aufgabe verknüpfen (damit er den Fortschritt misst: D). Wenn Sie beispielsweise eine Datei per FTP übertragen, können Sie ftplib anweisen, einen Puffer mit einer bestimmten Größe abzurufen, beispielsweise 128 KB, und dann Ihrem Fortschrittsbalken den Prozentsatz der Dateigröße hinzufügen, den 128 KB darstellen. Wenn Sie die CLI verwenden und Ihre Fortschrittsanzeige 20 Zeichen lang ist, würden Sie ein Zeichen hinzufügen, wenn 1/20 der Datei übertragen wurde.

Johncip
quelle
In meinem Fall verwende ich eine API, die keine Möglichkeit bietet, bestimmte Chunks abzurufen. Danke für die Idee, es ist schön.
user225312
0

@ 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 Methode update. Zum Beispiel: Lesen Sie alle Zeilen einer Testdatei und behandeln Sie sie mit 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 isteuert den Status von pbarüber die Methodeupdate

Tung
quelle
0

eine etwas allgemeinere Antwort von jelde015 (Kredit an ihn natürlich)

Zum manuellen Aktualisieren der Ladeleiste sind:

import sys
from math import *


def loadingBar(i, N, size):
    percent = float(i) / float(N)
    sys.stdout.write("\r"
                     + str(int(i)).rjust(3, '0')
                     +"/"
                     +str(int(N)).rjust(3, '0')
                     + ' ['
                     + '='*ceil(percent*size)
                     + ' '*floor((1-percent)*size)
                     + ']')

und nennen es:

loadingBar(7, 220, 40)

wird ergeben:

007/220 [=                                       ]  

Rufen Sie es einfach mit dem aktuellen iWert auf, wann immer Sie möchten .

setzen die sizeals die Anzahl der Zeichen sollte die Bar sein

Yarden Cohen
quelle
0

Ich schätze, ich bin etwas spät dran, aber dies sollte für Leute funktionieren, die mit den aktuellen Versionen von Python 3 arbeiten , da dies "f-Strings" verwendet , wie in Python 3.6 PEP 498 eingeführt :

Code

from numpy import interp

class Progress:
    def __init__(self, value, end, title='Downloading',buffer=20):
        self.title = title
        #when calling in a for loop it doesn't include the last number
        self.end = end -1
        self.buffer = buffer
        self.value = value
        self.progress()

    def progress(self):
        maped = int(interp(self.value, [0, self.end], [0, self.buffer]))
        print(f'{self.title}: [{"#"*maped}{"-"*(self.buffer - maped)}]{self.value}/{self.end} {((self.value/self.end)*100):.2f}%', end='\r')

Beispiel

#some loop that does perfroms a task
for x in range(21)  #set to 21 to include until 20
    Progress(x, 21)

Ausgabe

Downloading: [########------------] 8/20 40.00%
Gustavo Barros
quelle
0

Dies ist eine einfache Möglichkeit, einen Fortschrittsbalken zu erstellen

import time,sys
toolbar_width = 50
# setting up toolbar [-------------------------------------]
sys.stdout.write("[%s]"%(("-")*toolbar_width))
sys.stdout.flush()
# each hash represents 2 % of the progress
for i in range(toolbar_width):
    sys.stdout.write("\r") # return to start of line
    sys.stdout.flush()
    sys.stdout.write("[")#Overwrite over the existing text from the start 
    sys.stdout.write("#"*(i+1))# number of # denotes the progress completed 
    sys.stdout.flush()
    time.sleep(0.1)
Prasaanth Selvakumar
quelle