Pasek postępu Python


307

Jak korzystać z paska postępu, gdy mój skrypt wykonuje jakieś zadania, które mogą zająć trochę czasu?

Na przykład funkcja, której ukończenie zajmuje trochę czasu, a po zakończeniu wraca True. Jak mogę wyświetlić pasek postępu podczas wykonywania funkcji?

Pamiętaj, że muszę to robić w czasie rzeczywistym, więc nie mogę wymyślić, co z tym zrobić. Czy potrzebuję threaddo tego? Nie mam pojęcia.

W tej chwili nie drukuję niczego podczas wykonywania funkcji, jednak pasek postępu byłby miły. Jestem również bardziej zainteresowany tym, jak można to zrobić z punktu widzenia kodu.


Czy używasz tylko GUI lub CLI?
Bobby

CLI. Ale mogę korzystać z biblioteki innej firmy, to nie jest problem. Z GUI mogę to zrobić, ale interesowała mnie część CLI.
user225312

1
Możliwy duplikat paska postępu tekstu w konsoli Uwaga: chociaż to pytanie zostało opublikowane trzy dni wcześniej, połączone pytanie jest częściej wyświetlane.
Greenstick,

Oto rozwiązanie w notesie Jupyter: mikulskibartosz.name/...
Steven C. Howell

Opublikowałem nowy rodzaj paska postępu, który możesz wydrukować, zobaczyć przepustowość i eta, a nawet wstrzymać go, oprócz bardzo fajnych animacji! Proszę spojrzeć: github.com/rsalmei/alive-progress ! alive-progress
rsalmei

Odpowiedzi:


185

Istnieją określone biblioteki ( jak ta tutaj ), ale może coś bardzo prostego by zrobiło:

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

Uwaga: progressbar2 to rozwidlenie paska postępu, który nie był utrzymywany od lat.


14
to nie jest skalowane dla wielu kroków ... pypi.python.org/pypi/progress jest znacznie łatwiejszy w użyciu
m13r

5
Wypróbowałem ten kod i zgłosił NameError: name 'xrange' is not definedbłąd. Czy brakuje mi modułu?
Mushroom Man

6
@ GokuMcSpock9733 Której wersji Pythona używasz? Python's 2 xrangeto Python's 3 range.
quapka

9
To nie powinna być najlepsza odpowiedź. Druga odpowiedź (z tqdm) jest przynajmniej dla mnie znacznie lepsza.
Florian,

1
Pasek postępu biednych w Pythonie 3:print('■', end='', flush=True)
PatrickT

351

Dzięki tqdm możesz dodać wskaźnik postępu do swoich pętli w ciągu sekundy:

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]

Istnieje również graficzna wersja tqdm od 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)

okno GUI tqdm

Ale bądź ostrożny, ponieważ tqdm_guimożesz podnieść a TqdmExperimentalWarning: GUI is experimental/alpha, możesz go zignorować za pomocą warnings.simplefilter("ignore"), ale później zignoruje wszystkie ostrzeżenia w twoim kodzie.


9
To jedyne rozwiązanie, które znalazłem do pracy z terminalem, qtconsole i notebookiem
Ivelin

3
Czy to działa z dowolnym iterowalnym? Mam problem z uruchomieniem go z listą ciągów.
Josh Usre,

3
@JoshUsre Tak, powinien współpracować z każdym iterowalnym, na razie nie widziałem żadnego iterowalnego, który byłby zadławiony. Jednak wyświetlenie ETA (pozostały czas) wymaga iterowalności posiadania __len__właściwości lub użytkownik musi podać totalargument tqdm. W przeciwnym razie pasek będzie działał, ale bez ETA.
nudny

6
@gaborous: Dlaczego to nie jest najczęściej głosowana odpowiedź? To proste rozwiązanie działa zarówno w terminalu, jak i w notatniku Jupyter, w przeciwieństwie do najwyższej odpowiedzi.
Ébe Isaac

6
do uruchamiania w notatniku jupyter from tqdm import tqdm_notebook as tqdm. W przeciwnym razie nie pisze tego w jednym wierszu.
Jacques MALAPRADE

81

Powyższe sugestie są całkiem dobre, ale myślę, że większość ludzi chce tylko gotowego rozwiązania, bez zależności od zewnętrznych pakietów, ale można go również użyć ponownie.

Zdobyłem najlepsze punkty z wszystkich powyższych i przekształciłem je w funkcję wraz z przypadkami testowymi.

Aby go użyć, po prostu skopiuj linie pod „def update_progress (progress)”, ale nie skrypt testowy. Nie zapomnij zaimportować sys. Zadzwoń do tego, ilekroć chcesz wyświetlić lub zaktualizować pasek postępu.

Działa to poprzez bezpośrednie wysłanie symbolu „\ r” do konsoli, aby przesunąć kursor z powrotem na początek. „print” w pythonie nie łączy w tym celu powyższego symbolu, dlatego potrzebujemy „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)

Oto wynik skryptu testowego (animuje ostatni pasek postępu):

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

10
Animowany test (ostatni) powinien powiedzieć in range(101)nie 100, postęp zatrzymuje się na 99% i nigdy nie wyświetla się jako gotowy.
Nick Humrich

41

Ta odpowiedź nie zależy od zewnętrznych pakietów , myślę też, że większość ludzi chce tylko gotowego fragmentu kodu . Poniższy kod można dostosować do własnych potrzeb, dostosowując: symbol postępu '#'paska size, pasek , tekst prefixitp.

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

Stosowanie:

import time

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

Wynik:

Computing: [################........................] 4/15
  • Nie wymaga drugiego wątku . Niektóre powyższe rozwiązania / pakiety wymagają. Drugi wątek może stanowić problem jupyter notebook, na przykład.

  • Działa z każdym iterowalnym, co oznacza wszystko, czego len()można użyć. A list, dictcokolwiek na przykład['a', 'b', 'c' ... 'g']

Możesz także zmienić dane wyjściowe, zmieniając sys.stderrna przykład plik


Podoba mi się to rozwiązanie, generatory generują następujący błąd:TypeError: object of type 'generator' has no len()
jabellcu

@jabellcu w takim przypadku ( generators) musisz owinąć go list(). Likefor i in progressbar(list(your_generator), "Computing: ", 40):
eusoubrasileiro,

22

dla podobnej aplikacji (śledzenie postępu w pętli) po prostu użyłem paska postępu Pythona :

Ich przykład brzmi mniej więcej tak:

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

3
Aby uzyskać zgodność z Python 3, wypróbuj progressbar2pakiet. Powyższy kod będzie z nim współpracował.
d33tah,

2
Czy naprawdę po prostu użyłeś import *?
eryczny

20

Wypróbuj postępy z 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()

Wynikiem będzie pasek taki jak poniżej:

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

Właśnie tego spróbowałem. BARDZO łatwy w użyciu. Zajęło mi to około 2 minut (w tym postęp instalacji pip), aby pasek stanu był uruchomiony.
perelin

progresstworzy ładne słupki, ale zawodzi, jeśli inne oprogramowanie manipuluje stderr. przepraszam, ale nie zbadałem dokładnego problemu.
Arthur

Drukuje jedną linię dla każdego postępu w mojej konsoli Ubuntu, na przykład, jeśli max = 20, drukuje 20 linii ... Jak sprawić, aby drukowała tylko jedną linię?
L's World

19

Właśnie zrobiłem prostą klasę postępów dla moich potrzeb po wyszukaniu tutaj równoważnego rozwiązania. Myślałem, że mogę to opublikować.

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)

Przykład:

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

Wydrukuje następujące:

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


3
Wspaniale, dziękuję za to. BTW, możesz dodać progress.currentinkrementację na końcu, __call__aby jeszcze bardziej ograniczyć interakcję z obiektem z kodu głównego.
npit

Ten kod jest prosty, zwięzły i użyteczny! Dziękuję Ci!
Ian Rehwinkel

15

Podoba mi się odpowiedź Briana Khuu za jej prostotę i brak potrzeby korzystania z zewnętrznych pakietów. Trochę go zmieniłem, więc dodaję tutaj swoją wersję:

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)

Przyjmuje całkowitą liczbę przebiegów ( total) i liczbę przebiegów przetworzonych do tej pory ( progress) przy założeniu total >= progress. Wynik wygląda następująco:

[#####---------------] 27%

14

Możesz użyć tqdm :

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)

W tym przykładzie pasek postępu działa przez 5 minut i jest pokazany w następujący sposób:

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

Możesz to zmienić i dostosować do swoich potrzeb.


11

Aby użytkować dowolne ramy paska postępu w przydatny sposób, tj. Uzyskać rzeczywisty procent postępu i szacunkową ETA, musisz być w stanie zadeklarować, ile będzie on miał kroków.

A więc, jeśli obliczasz funkcję w innym wątku, czy jesteś w stanie podzielić ją na kilka logicznych kroków? Czy możesz zmodyfikować jego kod?

Nie musisz go refaktoryzować ani dzielić na rzeczywiste metody, możesz po prostu umieścić strategiczne yieldw niektórych miejscach w środku! Jeśli droga funkcja ma pętlę for , po prostu włóż ją do niej. Na koniec powinieneś wiedzieć tylko, ile plonów zostanie zrobionych, aby uzyskać najlepsze wyniki.

W ten sposób twoja funkcja może wyglądać mniej więcej tak:

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

albo to:

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

Za pomocą tego rodzaju funkcji możesz zainstalować:

pip install alive-progress

I używaj go w następujący sposób:

from alive_progress import alive_bar

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

Aby uzyskać fajny pasek postępu!

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

Oświadczenie: Jestem autorem alive_progress, ale powinno to dobrze rozwiązać Twój problem. Przeczytaj dokumentację na https://github.com/rsalmei/alive-progress , oto przykład tego, co może zrobić:

żywy postęp


8

Naprawdę podoba mi się pasek postępu Pythona , ponieważ jest bardzo prosty w użyciu.

W najprostszym przypadku jest to po prostu:

import progressbar
import time

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

Wygląd można dostosować i wyświetlać szacowany pozostały czas. Na przykład użyj tego samego kodu jak powyżej, ale z:

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

5

Jeśli jest to duża pętla ze stałą liczbą iteracji, która zajmuje dużo czasu, możesz użyć tej funkcji, którą wykonałem. Każda iteracja pętli dodaje postęp. Gdzie count jest bieżącą iteracją pętli, suma to wartość, do której zapętlasz, a rozmiar (int) to, jak duży chcesz pasek w odstępach co 10, tj. (Rozmiar 1 = 10 znaków, rozmiar 2 = 20 znaków)

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 + ']')

przykład:

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

wynik:

i = 50
>> 050/100 [==========          ]


4

Poniższy kod jest dość ogólnym rozwiązaniem, ma również czas, który upłynął i szacowany pozostały czas. Możesz użyć dowolnej iterowalnej z nim. Pasek postępu ma stały rozmiar 25 znaków, ale może wyświetlać aktualizacje w krokach co 1%, używając znaków pełnego, pół i kwartału. Dane wyjściowe wyglądają następująco:

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

Kod z przykładem:

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)

Sugestie dotyczące ulepszeń lub inne komentarze są mile widziane. Twoje zdrowie!


3

Podoba mi się ta strona .

Zaczyna się od prostego przykładu i przechodzi do wersji wielowątkowej. Działa po wyjęciu z pudełka. Nie są wymagane żadne pakiety stron trzecich.

Kod będzie wyglądał mniej więcej tak:

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)

Lub tutaj jest przykład użycia wątków w celu uruchomienia obracającego się paska ładowania podczas działania programu:

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

3

W Python3 jest to dość proste:

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

3

Podczas pracy w notebookach jupyter normalne tqdm nie działa, ponieważ zapisuje dane wyjściowe w wielu wierszach. Zamiast tego użyj tego:

import time
from tqdm import tqdm_notebook as tqdm

for i in tqdm(range(100))
    time.sleep(0.5)

2

Jeśli twojej pracy nie można podzielić na mierzalne fragmenty, możesz wywołać swoją funkcję w nowym wątku i określić czas, jaki to zajmie:

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"

Możesz oczywiście zwiększyć dokładność taktowania zgodnie z wymaganiami.


Gdzie w odpowiedzi odpowiadałaby praca mierzona w kodzie?
unseen_rider

2

Podoba mi się odpowiedź Gabriela , ale zmieniłem ją na elastyczną. Możesz wysłać długość paska do funkcji i uzyskać pasek postępu o dowolnej długości. I nie możesz mieć paska postępu o zerowej lub ujemnej długości. Możesz także użyć tej funkcji jak odpowiedź Gabriela (patrz przykład 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)

Wynik:

To jest prosty pasek postępu.

Przykład 1

Postęp: [### -------] 30%

Przykład nr 2

Postęp: [||||||||||||| ........] 60%

Gotowy.


2

Użyłem format()metody, aby zrobić pasek obciążenia. Oto moje rozwiązanie:

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

Wynik:

[#######################] - 100.00%

1

Oto krótkie rozwiązanie, które programowo buduje pasek ładowania (musisz zdecydować, jak długo chcesz).

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)

1

Wypróbuj PyProg. PyProg to otwarta biblioteka dla Pythona do tworzenia super dostosowywalnych wskaźników i pasków postępu.

Obecnie jest w wersji 1.0.2; jest hostowany na Github i dostępny na PyPI (linki poniżej). Jest kompatybilny z Python 3 i 2 i może być również używany z Qt Console.

Jest naprawdę łatwy w użyciu. Poniższy kod:

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

będzie produkować:

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

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

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

Zrobiłem PyProg, ponieważ potrzebowałem prostej, ale super konfigurowalnej biblioteki paska postępu. Można łatwo zainstalować go z: pip install pyprog.

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


1

Możesz także użyć oświecenia . Główną zaletą jest to, że możesz logować się jednocześnie bez nadpisywania paska postępu.

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

Obsługuje także wiele pasków postępu.

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

1

Skorzystaj z biblioteki postępu !

pip install progress

Oto niestandardowa podklasa, którą napisałem, aby sformatować czasy ETA / Upływające w lepszym formacie:

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

1

To jest moje proste rozwiązanie:

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

Powinieneś połączyć pasek postępu z danym zadaniem (aby mierzył postęp: D). Na przykład, jeśli przesyłasz plik przez FTP, możesz powiedzieć ftplib, aby pobierał bufor o określonym rozmiarze, powiedzmy 128K, a następnie dodajesz do paska postępu dowolny procent wielkości pliku, który reprezentuje 128k. Jeśli korzystasz z interfejsu CLI, a wskaźnik postępu ma 20 znaków, możesz dodać jeden znak po przesłaniu 1/20 pliku.


W moim przypadku korzystam z interfejsu API i nie zapewnia on możliwości pobierania określonych porcji. Dzięki za pomysł, to jest miłe.
user225312,

0

@Massagran: Działa dobrze w moich programach. Ponadto musimy dodać licznik wskazujący czasy pętli. Ten licznik odgrywa rolę argumentu metody update. Na przykład: przeczytaj wszystkie wiersze pliku testowego i potraktuj je na czymś. Załóżmy, że funkcja dosth()nie dotyczy zmiennej 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()

Zmienna ikontroluje status pbarza pomocą metodyupdate


0

nieco bardziej ogólna odpowiedź na jelde015 (oczywiście mu się przypisuje)

do ręcznej aktualizacji paska ładowania będzie:

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)
                     + ']')

i nazywając to:

loadingBar(7, 220, 40)

skutkuje:

007/220 [=                                       ]  

po prostu zadzwoń, gdy chcesz, z bieżącą iwartością.

ustaw sizeliczbę znaków, jaką powinien mieć pasek


0

Myślę, że jestem trochę spóźniony, ale powinno to działać dla osób pracujących z aktualnymi wersjami Pythona 3 , ponieważ używa to „ciągów-f” , jak wprowadzono w Pythonie 3.6 PEP 498 :

Kod

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

Przykład

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

Wynik

Downloading: [########------------] 8/20 40.00%

0

Jest to prosty sposób na utworzenie paska postępu

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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.