Barra di avanzamento di Python


307

Come posso utilizzare una barra di avanzamento quando il mio script sta eseguendo un'attività che probabilmente richiederà tempo?

Ad esempio, una funzione che richiede del tempo per il completamento e al termine restituisce True. Come posso visualizzare una barra di avanzamento durante l'esecuzione della funzione?

Nota che ho bisogno che questo sia in tempo reale, quindi non riesco a capire cosa fare al riguardo. Ho bisogno di un threadper questo? Non ne ho idea.

In questo momento non sto stampando nulla mentre la funzione è in esecuzione, tuttavia sarebbe utile una barra di avanzamento. Inoltre sono più interessato a come questo può essere fatto da un punto di vista del codice.


Stai usando solo un toolkit GUI o una CLI?
Bobby,

CLI. Ma posso usare una libreria di terze parti, questo non è un problema. Con la GUI posso farlo, ma ero interessato alla parte CLI.
user225312

1
Possibile duplicato della barra di avanzamento del testo nella console Si noti che mentre questa domanda è stata pubblicata tre giorni prima, la domanda collegata viene visualizzata più frequentemente.
Greenstick,

Ecco una soluzione per un notebook Jupyter
Steven C. Howell,

Ho pubblicato un nuovo tipo di barra di avanzamento, che puoi stampare, vedere la velocità effettiva e eta, persino metterla in pausa, oltre alle animazioni molto interessanti! Dai un'occhiata: github.com/rsalmei/alive-progress ! alive-progress
rsalmei,

Risposte:


185

Ci sono librerie specifiche ( come questa qui ) ma forse qualcosa di molto semplice farebbe:

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

Nota: progressbar2 è un fork di progressbar che non è stato mantenuto per anni.


14
questo non si adatta a molti passaggi ... pypi.python.org/pypi/progress è molto più facile da usare
m13r

5
Ho provato questo codice e ha NameError: name 'xrange' is not definedgenerato un errore. Mi manca un modulo?
Mushroom Man,

6
@ GokuMcSpock9733 Quale versione di Python stai usando? Python's 2 xrangeè Python's 3 range.
quapka,

9
Questa non dovrebbe essere la risposta migliore. L'altra risposta (con tqdm) è molto meglio per me almeno.
Florian,

1
Barra di avanzamento dei poveri in Python 3:print('■', end='', flush=True)
PatrickT

352

Con tqdm puoi aggiungere un indicatore di progresso ai tuoi loop in un secondo:

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]

Inoltre, esiste una versione grafica di tqdm poiché 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)

finestra gui tqdm

Ma fai attenzione, poiché tqdm_guipuò sollevare un TqdmExperimentalWarning: GUI is experimental/alpha, puoi ignorarlo usando warnings.simplefilter("ignore"), ma successivamente ignorerà tutti gli avvisi nel tuo codice.


9
Questa è l'unica soluzione che ho trovato per funzionare con terminal, qtconsole e notebook
Ivelin

3
Funziona con qualsiasi iterabile? Ho avuto problemi a farlo funzionare con un elenco di stringhe.
Josh Usre,

3
@JoshUsre Sì, dovrebbe funzionare con qualsiasi iterabile, per il momento non ho visto alcun iterabile su cui si soffocava. Tuttavia, la visualizzazione dell'ETA (tempo rimanente) richiede che l'iterabile abbia una __len__proprietà o l'utente deve fornire l' totalargomento tqdm. Altrimenti, il bar funzionerà ma senza ETA.
Gaborous,

6
@gaborous: come mai questa non è la risposta più votata? Questa semplice soluzione funziona sia nel terminale che nel notebook Jupyter a differenza della risposta migliore.
Ébe Isaac,

6
per l'esecuzione in un notebook jupyter from tqdm import tqdm_notebook as tqdm. Altrimenti non lo scrive su una riga.
Jacques MALAPRADE,

81

I suggerimenti di cui sopra sono abbastanza buoni, ma penso che la maggior parte delle persone voglia solo una soluzione pronta, senza dipendenze da pacchetti esterni, ma è anche riutilizzabile.

Ho ottenuto i punti migliori di tutto quanto sopra e l'ho trasformato in una funzione, insieme a casi di test.

Per usarlo, basta copiare le righe in "def update_progress (progress)" ma non lo script di test. Non dimenticare di importare sys. Chiamalo ogni volta che devi visualizzare o aggiornare la barra di avanzamento.

Funziona inviando direttamente il simbolo "\ r" alla console per riportare il cursore all'inizio. "print" in python non ricongiunge il simbolo sopra per questo scopo, quindi abbiamo bisogno di '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)

Questo è ciò che mostra il risultato dello script di test (L'ultima barra di avanzamento anima):

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
Il test animato (ultimo) dovrebbe dire in range(101)non 100, l'avanzamento si ferma al 99% e non viene mai visualizzato.
Nick Humrich,

41

Questa risposta non si basa su pacchetti esterni , penso anche che la maggior parte delle persone voglia solo un pezzo di codice già pronto . Il codice seguente può essere adattato per soddisfare le tue esigenze personalizzando: barra di avanzamento '#', barra size, testo prefixecc.

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

Uso:

import time

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

Produzione:

Computing: [################........................] 4/15
  • Non richiede un secondo thread . Alcune soluzioni / pacchetti sopra richiedono. Un secondo thread può essere un problema jupyter notebook, ad esempio un.

  • Funziona con qualsiasi iterabile , significa tutto ciò su cui len()può essere utilizzato. A list, a dictdi tutto per esempio['a', 'b', 'c' ... 'g']

È inoltre possibile modificare l'output modificando il file in sys.stderrad esempio


Mi piace questa soluzione, i generatori TypeError: object of type 'generator' has no len()
genereranno

@jabellcu in quel caso ( generators) devi avvolgerlo con a list(). Mi piacefor i in progressbar(list(your_generator), "Computing: ", 40):
eusoubrasileiro

22

per un'applicazione simile (tenendo traccia dell'avanzamento in un ciclo) ho semplicemente usato la barra di avanzamento python :

Il loro esempio è simile a questo,

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
Per la compatibilità con Python 3, prova il progressbar2pacchetto. Il codice sopra funzionerà con esso.
d33tah,

2
Hai appena usato import *?
eric,

20

Prova i progressi da 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()

Il risultato sarà una barra come la seguente:

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

Ho appena provato questo. MOLTO facile da usare. Mi ci sono voluti 2 minuti (incluso l'avanzamento dell'installazione del pip) per avere una barra di stato attiva e funzionante.
perelin,

progresscrea delle belle barre, ma fallisce se altri software stanno manipolando stderr. scusa, ma non ho studiato il problema esatto.
Arthur,

Stampa una riga per ogni progresso nella mia console Ubuntu, ad esempio, se max = 20, stampa 20 righe ... Come faccio a stamparla solo una riga?
L's World,

19

Ho appena fatto una semplice classe di progresso per le mie esigenze dopo aver cercato qui una soluzione equivalente. Ho pensato di poterlo pubblicare bene.

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)

Esempio :

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

Stampa quanto segue:

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


3
Fantastico, grazie per questo. A proposito, puoi aggiungere l' progress.currentincremento alla fine di __call__per limitare ulteriormente l'interazione con l'oggetto dal codice principale.
npit,

Questo codice è semplice, conciso e utile! Grazie!
Ian Rehwinkel,

15

Mi piace la risposta di Brian Khuu per la sua semplicità e non necessita di pacchetti esterni. L'ho cambiato un po ', quindi sto aggiungendo la mia versione qui:

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)

Prende il numero totale di esecuzioni ( total) e il numero di esecuzioni elaborate finora ( progress) assumendo total >= progress. Il risultato è simile al seguente:

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

14

Puoi usare 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)

In questo esempio la barra di avanzamento è in esecuzione per 5 minuti e viene visualizzata in questo modo:

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

Puoi cambiarlo e personalizzarlo come preferisci.


11

Per utilizzare qualsiasi framework di barra di avanzamento in modo utile, ad esempio per ottenere una percentuale di avanzamento effettiva e un ETA stimato, è necessario essere in grado di dichiarare quanti passaggi avrà.

Quindi, la tua funzione di calcolo in un altro thread, sei in grado di dividerlo in una serie di passaggi logici? Puoi modificarne il codice?

Non hai bisogno di riformattarlo o dividerlo in metodi reali, potresti semplicemente mettere alcuni yields strategici in alcuni punti al suo interno! Se la costosa funzione ha un ciclo for , inseriscene uno. Alla fine dovresti solo sapere quante rese verranno fatte, per ottenere i migliori risultati.

In questo modo, la tua funzione potrebbe essere qualcosa del genere:

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

o questo:

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

Con quel tipo di funzione, puoi installare:

pip install alive-progress

E usalo come:

from alive_progress import alive_bar

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

Per ottenere una barra di avanzamento interessante!

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

Disclaimer: sono l'autore di alive_progress, ma dovrebbe risolvere bene il tuo problema. Leggi la documentazione su https://github.com/rsalmei/alive-progress , ecco un esempio di cosa può fare:

viva-progress


8

Mi piace molto la barra di avanzamento di Python , in quanto è molto semplice da usare.

Per il caso più semplice, è solo:

import progressbar
import time

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

L'aspetto può essere personalizzato e può visualizzare il tempo rimanente stimato. Per un esempio usa lo stesso codice sopra ma con:

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

5

Se è un grande loop con un numero fisso di iterazioni che richiede molto tempo, puoi usare questa funzione che ho creato. Ogni iterazione di loop aggiunge progressi. Dove count è l'attuale iterazione del loop, total è il valore a cui stai eseguendo il loop e size (int) è quanto vuoi che la barra sia in incrementi di 10 cioè (dimensione 1 = 10 caratteri, dimensione 2 = 20 caratteri)

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

esempio:

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

produzione:

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


4

Il codice seguente è una soluzione abbastanza generale e ha anche una stima del tempo trascorso e del tempo rimanente. Puoi usare qualsiasi iterabile con esso. La barra di avanzamento ha una dimensione fissa di 25 caratteri ma può mostrare gli aggiornamenti con incrementi dell'1% utilizzando caratteri a pieno, mezzo e quarto blocco. L'output è simile al seguente:

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

Codice con esempio:

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)

Sono apprezzati suggerimenti per miglioramenti o altri commenti. Saluti!


3

Mi piace questa pagina .

Inizia con un semplice esempio e passa a una versione multi-thread. Funziona fuori dalla scatola. Non sono richiesti pacchetti di terze parti.

Il codice sarà simile al seguente:

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)

Oppure ecco un esempio per usare i thread per eseguire la barra di caricamento rotante mentre il programma è in esecuzione:

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

È abbastanza semplice in Python3:

   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

Quando si esegue su notebook jupyter l'uso di tqdm normale non funziona, poiché scrive l'output su più righe. Usa questo invece:

import time
from tqdm import tqdm_notebook as tqdm

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

2

Se il tuo lavoro non può essere suddiviso in blocchi misurabili, puoi chiamare la tua funzione in un nuovo thread e il tempo che impiega:

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"

È ovviamente possibile aumentare la precisione di temporizzazione come richiesto.


Dove si potrebbe fare il lavoro da misurare nel codice in risposta?
unseen_rider,

2

Mi piace la risposta di Gabriel , ma l'ho cambiata per renderla flessibile. È possibile inviare la lunghezza della barra alla funzione e ottenere la barra di avanzamento con la lunghezza desiderata. E non puoi avere una barra di avanzamento con lunghezza zero o negativa. Inoltre, puoi usare questa funzione come la risposta di Gabriel (Guarda l'esempio n. 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)

Risultato:

Questa è una semplice barra di avanzamento.

Esempio 1

Progresso: [### -------] 30%

Esempio n. 2

Progresso: [|||||||||||| ........] 60%

Fatto.


2

Ho usato il format()metodo per creare una barra di caricamento. Ecco la mia soluzione:

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

Produzione:

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

1

Ecco una breve soluzione che costruisce la barra di caricamento a livello di codice (devi decidere per quanto tempo la vuoi).

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

Prova PyProg. PyProg è una libreria open source per Python per creare indicatori e barre di avanzamento super personalizzabili.

È attualmente alla versione 1.0.2; è ospitato su Github e disponibile su PyPI (link in basso). È compatibile con Python 3 e 2 e può essere utilizzato anche con Qt Console.

È davvero facile da usare. Il seguente codice:

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

produrrà:

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

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

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

In realtà ho creato PyProg perché avevo bisogno di una libreria di barre di avanzamento semplice ma super personalizzabile. Si può facilmente installare con: pip install pyprog.

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


1

Puoi anche usare illuminare . Il vantaggio principale è che è possibile accedere contemporaneamente senza sovrascrivere la barra di avanzamento.

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

Gestisce anche più barre di avanzamento.

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

Usa la libreria dei progressi !

pip install progress

Ecco una sottoclasse personalizzata che ho scritto per formattare i tempi ETA / Elapsed in un formato leggibile meglio:

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

Questa è la mia soluzione semplice:

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

È necessario collegare la barra di avanzamento all'attività in corso (in modo che misuri l'avanzamento: D). Ad esempio, se stai inviando un file FTP, puoi dire a ftplib di prendere un certo buffer di dimensioni, diciamo 128K, e poi aggiungi alla tua barra di avanzamento qualunque percentuale del file 128k rappresenti. Se si utilizza l'interfaccia della riga di comando e l'indicatore di avanzamento ha una lunghezza di 20 caratteri, si dovrebbe aggiungere un carattere dopo il trasferimento di 1/20 del file.


Nel mio caso sto usando un'API e non offre alcuna possibilità per ottenere blocchi specifici. Grazie per l'idea, è bello.
user225312

0

@Massagran: funziona bene nei miei programmi. Inoltre, è necessario aggiungere un contatore per indicare i tempi di ciclo. Questo contatore gioca come argomento del metodo update. Ad esempio: leggi tutte le righe di un file di prova e trattale su qualcosa. Supponiamo che la funzione dosth()non riguardi la variabile 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()

La variabile icontrolla lo stato di pbartramite il metodoupdate


0

una risposta un po 'più generica di jelde015 (merito a lui ovviamente)

per aggiornare manualmente la barra di caricamento saranno:

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

e chiamandolo da:

loadingBar(7, 220, 40)

risulterà:

007/220 [=                                       ]  

chiamalo quando vuoi con la corrente i valore .

imposta sizecome il numero di caratteri che la barra dovrebbe essere


0

Suppongo che sono un po 'in ritardo, ma questo dovrebbe funzionare per le persone che lavorano con le versioni attuali di Python 3 , poiché utilizza "f-string" , come introdotto in Python 3.6 PEP 498 :

Codice

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

Esempio

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

Produzione

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

0

Questo è un modo semplice per creare una barra di avanzamento

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.