una progreso hacer como barra bar python console progress updating

progreso - python progress bar



Barra de progreso de texto en la consola (30)

¿Hay una buena manera de hacer lo siguiente?

Escribí una aplicación de consola simple para cargar y descargar archivos desde un servidor FTP utilizando el ftplib.

Cada vez que se descargan algunos fragmentos de datos, quiero actualizar una barra de progreso de texto, incluso si es solo un número.

Pero no quiero borrar todo el texto que se ha impreso en la consola. (Haciendo un "claro" y luego imprimiendo el porcentaje actualizado.)


Aquí está mi solución de Python 3:

import time for i in range(100): time.sleep(1) s = "{}% Complete".format(i) print(s,end=len(s) * ''/b'')

''/ b'' es una barra invertida, para cada carácter en su cadena. Esto no funciona dentro de la ventana de cmd de Windows.


Aquí hay un agregado de muchas de las respuestas a continuación que uso regularmente.

# Print iterations progress def printProgressBar (iteration, total, prefix = '''', suffix = '''', decimals = 1, length = 100, fill = ''█''): """ Call in a loop to create terminal progress bar @params: iteration - Required : current iteration (Int) total - Required : total iterations (Int) prefix - Optional : prefix string (Str) suffix - Optional : suffix string (Str) decimals - Optional : positive number of decimals in percent complete (Int) length - Optional : character length of bar (Int) fill - Optional : bar fill character (Str) """ percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) filledLength = int(length * iteration // total) bar = fill * filledLength + ''-'' * (length - filledLength) print(''/r%s |%s| %s%% %s'' % (prefix, bar, percent, suffix), end = ''/r'') # Print New Line on Complete if iteration == total: print() # # Sample Usage # from time import sleep # A List of Items items = list(range(0, 57)) l = len(items) # Initial call to print 0% progress printProgressBar(0, l, prefix = ''Progress:'', suffix = ''Complete'', length = 50) for i, item in enumerate(items): # Do stuff... sleep(0.1) # Update Progress Bar printProgressBar(i + 1, l, prefix = ''Progress:'', suffix = ''Complete'', length = 50) # Sample Output Progress: |█████████████████████████████████████████████-----| 90.0% Complete


Bueno, aquí hay un código que funciona y lo probé antes de publicar:

import sys def prg(prog, fillchar, emptchar): fillt = 0 emptt = 20 if prog < 100 and prog > 0: prog2 = prog/5 fillt = fillt + prog2 emptt = emptt - prog2 sys.stdout.write("/r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%") sys.stdout.flush() elif prog >= 100: prog = 100 prog2 = prog/5 fillt = fillt + prog2 emptt = emptt - prog2 sys.stdout.write("/r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%" + "/nDone!") sys.stdout.flush() elif prog < 0: prog = 0 prog2 = prog/5 fillt = fillt + prog2 emptt = emptt - prog2 sys.stdout.write("/r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%" + "/nHalted!") sys.stdout.flush()

Pros:

  • Barra de 20 caracteres (1 carácter por cada 5 (número))
  • Caracteres de relleno personalizados
  • Caracteres vacíos personalizados
  • Detener (cualquier número por debajo de 0)
  • Hecho (100 y cualquier número por encima de 100)
  • Recuento de progreso (0-100 (por debajo y por encima utilizado para funciones especiales)
  • Número de porcentaje junto a la barra, y es una sola línea

Contras:

  • Solo es compatible con enteros (aunque se puede modificar para prog2 = prog/5 , al hacer que la división sea una división entera, así que simplemente cambie prog2 = prog/5 a prog2 = int(prog/5) )

Código para la barra de progreso de la terminal de Python

import sys import time max_length = 5 at_length = max_length empty = "-" used = "%" bar = empty * max_length for i in range(0, max_length): at_length -= 1 #setting empty and full spots bar = used * i bar = bar+empty * at_length #/r is carriage return(sets cursor position in terminal to start of line) #/0 character escape sys.stdout.write("[{}]/0/r".format(bar)) sys.stdout.flush() #do your stuff here instead of time.sleep time.sleep(1) sys.stdout.write("/n") sys.stdout.flush()


Con los grandes consejos anteriores trabajo la barra de progreso.

Sin embargo, me gustaría señalar algunas deficiencias

  1. Cada vez que la barra de progreso se vacía, se iniciará en una nueva línea.

    print(''/r[{0}]{1}%''.format(''#'' * progress* 10, progress))

    Me gusta esto:
    [] 0%
    [#] 10%
    [##] 20%
    [###] 30%

2.El corchete '']'' y el número de porcentaje en el lado derecho se desplazan hacia la derecha a medida que ''###'' se alarga.
3. Se producirá un error si la expresión ''progreso / 10'' no puede devolver un entero.

Y el siguiente código solucionará el problema anterior.

def update_progress(progress, total): print(''/r[{0:10}]{1:>2}%''.format(''#'' * int(progress * 10 /total), progress), end='''')


Consulta esta biblioteca: clint

Tiene muchas características que incluyen una barra de progreso:

from time import sleep from random import random from clint.textui import progress if __name__ == ''__main__'': for i in progress.bar(range(100)): sleep(random() * 0.2) for i in progress.dots(range(100)): sleep(random() * 0.2)

Este link proporciona una visión general rápida de sus características.


Ejecute esto en la línea de comandos de Python ( no en ningún entorno de desarrollo o IDE):

>>> import threading >>> for i in range(50+1): ... threading._sleep(0.5) ... print "/r%3d" % i, (''=''*i)+(''-''*(50-i)),

Funciona bien en mi sistema de Windows.


Es menos de 10 líneas de código.

La esencia aquí: https://gist.github.com/vladignatyev/06860ec2040cb497f0f3

import sys def progress(count, total, suffix=''''): bar_len = 60 filled_len = int(round(bar_len * count / float(total))) percents = round(100.0 * count / float(total), 1) bar = ''='' * filled_len + ''-'' * (bar_len - filled_len) sys.stdout.write(''[%s] %s%s ...%s/r'' % (bar, percents, ''%'', suffix)) sys.stdout.flush() # As suggested by Rom Ruben


Escribí una barra de progreso simple:

def bar(total, current, length=10, prefix="", filler="#", space=" ", oncomp="", border="[]", suffix=""): if len(border) != 2: print("parameter ''border'' must include exactly 2 symbols!") return None print(prefix + border[0] + (filler * int(current / total * length) + (space * (length - int(current / total * length)))) + border[1], suffix, "/r", end="") if total == current: if oncomp: print(prefix + border[0] + space * int(((length - len(oncomp)) / 2)) + oncomp + space * int(((length - len(oncomp)) / 2)) + border[1], suffix) if not oncomp: print(prefix + border[0] + (filler * int(current / total * length) + (space * (length - int(current / total * length)))) + border[1], suffix)

Como puede ver, tiene: longitud de barra, prefijo y sufijo, relleno, espacio, texto en barra en 100% (oncomp) y bordes

aquí un ejemplo:

from time import sleep, time start_time = time() for i in range(10): pref = str((i+1) * 10) + "% " complete_text = "done in %s sec" % str(round(time() - start_time)) sleep(1) bar(10, i + 1, length=20, prefix=pref, oncomp=complete_text)

en progreso

30% [###### ]

fuera completo

100% [ done in 9 sec ]


Escriba un /r en la consola. Eso es un "retorno de carro" que hace que todo el texto que sigue después se haga eco al principio de la línea. Algo como:

def update_progress(progress): print ''/r[{0}] {1}%''.format(''#''*(progress/10), progress)

lo que te dará algo como: [ ########## ] 100%


Escribir ''/ r'' moverá el cursor de nuevo al principio de la línea.

Esto muestra un contador de porcentaje:

import time import sys for i in range(100): time.sleep(1) sys.stdout.write("/r%d%%" % i) sys.stdout.flush()


Estoy usando el progreso de reddit . Me gusta porque puede imprimir el progreso de cada elemento en una línea y no debe borrar las impresiones del programa.

Editar: enlace fijo


Función de Greenstick para 2.7:

def printProgressBar (iteration, total, prefix = '''', suffix = '''',decimals = 1, length = 100, fill = ''#''): percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) filledLength = int(length * iteration // total) bar = fill * filledLength + ''-'' * (length - filledLength) print''/r%s |%s| %s%% %s'' % (prefix, bar, percent, suffix), sys.stdout.flush() # Print New Line on Complete if iteration == total: print()


Instale tqdm . ( pip install tqdm ) y utilícelo de la siguiente manera:

import time from tqdm import tqdm for i in tqdm(range(1000)): time.sleep(0.01)

Eso es una barra de progreso de 10 segundos que generará algo como esto:

47%|██████████████████▊ | 470/1000 [00:04<00:05, 98.61it/s]


Intenta instalar este paquete: pip install progressbar2 :

import time import progressbar for i in progressbar.progressbar(range(100)): time.sleep(0.02)

progresssbar github: https://github.com/WoLpH/python-progressbar


La barra de progreso del módulo de Python es una buena opción. Aquí está mi código típico:

import time import progressbar widgets = [ '' '', progressbar.Percentage(), '' '', progressbar.SimpleProgress(format=''(%(value_s)s of %(max_value_s)s)''), '' '', progressbar.Bar(''>'', fill=''.''), '' '', progressbar.ETA(format_finished=''- %(seconds)s -'', format=''ETA: %(seconds)s'', ), '' - '', progressbar.DynamicMessage(''loss''), '' - '', progressbar.DynamicMessage(''error''), '' '' ] bar = progressbar.ProgressBar(redirect_stdout=True, widgets=widgets) bar.start(100) for i in range(100): time.sleep(0.1) bar.update(i + 1, loss=i / 100., error=i) bar.finish()


Me doy cuenta de que llego tarde al juego, pero aquí hay un estilo de Yum (Red Hat) que escribí (no voy al 100% de precisión aquí, pero si estás usando una barra de progreso para ese nivel de precisión, entonces estás equivocado de todos modos):

import sys def cli_progress_test(end_val, bar_length=20): for i in xrange(0, end_val): percent = float(i) / end_val hashes = ''#'' * int(round(percent * bar_length)) spaces = '' '' * (bar_length - len(hashes)) sys.stdout.write("/rPercent: [{0}] {1}%".format(hashes + spaces, int(round(percent * 100)))) sys.stdout.flush()

Debe producir algo parecido a esto:

Percent: [############## ] 69%

... donde los soportes permanecen estacionarios y solo aumentan los hash.

Esto podría funcionar mejor como decorador. Para otro día...


Prueba la biblioteca de click escrita por el Mozart de Python, Armin Ronacher.

$ pip install click # both 2 and 3 compatible

Para crear una barra de progreso simple:

import click with click.progressbar(range(1000000)) as bar: for i in bar: pass

Esto es lo que parece:

# [###-------------------------------] 9% 00:01:14

Personalízalo a tu gusto contenido:

import click, sys with click.progressbar(range(100000), file=sys.stderr, show_pos=True, width=70, bar_template=''(_(_)=%(bar)sD(_(_| %(info)s'', fill_char=''='', empty_char='' '') as bar: for i in bar: pass

Apariencia personalizada:

(_(_)===================================D(_(_| 100000/100000 00:00:02

Hay incluso más opciones, ver la documentación de la API :

click.progressbar(iterable=None, length=None, label=None, show_eta=True, show_percent=None, show_pos=False, item_show_func=None, fill_char=''#'', empty_char=''-'', bar_template=''%(label)s [%(bar)s] %(info)s'', info_sep='' '', width=36, file=None, color=None)


Recomiendo usar tqdm - https://pypi.python.org/pypi/tqdm - que hace que sea fácil convertir cualquier iterable o proceso en una barra de progreso, y maneja todos los problemas con los terminales necesarios.

De la documentación: "tqdm puede admitir fácilmente devoluciones de llamada / enlaces y actualizaciones manuales. Aquí hay un ejemplo con urllib"

import urllib from tqdm import tqdm def my_hook(t): """ Wraps tqdm instance. Don''t forget to close() or __exit__() the tqdm instance once you''re done with it (easiest using `with` syntax). Example ------- >>> with tqdm(...) as t: ... reporthook = my_hook(t) ... urllib.urlretrieve(..., reporthook=reporthook) """ last_b = [0] def inner(b=1, bsize=1, tsize=None): """ b : int, optional Number of blocks just transferred [default: 1]. bsize : int, optional Size of each block (in tqdm units) [default: 1]. tsize : int, optional Total size (in tqdm units). If [default: None] remains unchanged. """ if tsize is not None: t.total = tsize t.update((b - last_b[0]) * bsize) last_b[0] = b return inner eg_link = ''http://www.doc.ic.ac.uk/~cod11/matryoshka.zip'' with tqdm(unit=''B'', unit_scale=True, miniters=1, desc=eg_link.split(''/'')[-1]) as t: # all optional kwargs urllib.urlretrieve(eg_link, filename=''/dev/null'', reporthook=my_hook(t), data=None)


Reuniendo algunas de las ideas que encontré aquí, y agregando el tiempo estimado restante:

import datetime, sys start = datetime.datetime.now() def print_progress_bar (iteration, total): process_duration_samples = [] average_samples = 5 end = datetime.datetime.now() process_duration = end - start if len(process_duration_samples) == 0: process_duration_samples = [process_duration] * average_samples process_duration_samples = process_duration_samples[1:average_samples-1] + [process_duration] average_process_duration = sum(process_duration_samples, datetime.timedelta()) / len(process_duration_samples) remaining_steps = total - iteration remaining_time_estimation = remaining_steps * average_process_duration bars_string = int(float(iteration) / float(total) * 20.) sys.stdout.write( "/r[%-20s] %d%% (%s/%s) Estimated time left: %s" % ( ''=''*bars_string, float(iteration) / float(total) * 100, iteration, total, remaining_time_estimation ) ) sys.stdout.flush() if iteration + 1 == total: print # Sample usage for i in range(0,300): print_progress_bar(i, 300)


Una solución muy simple es poner este código en su bucle:

Ponga esto en el cuerpo (es decir, arriba) de su archivo:

import sys

Pon esto en el cuerpo de tu bucle:

sys.stdout.write("-") # prints a dash for each iteration of loop sys.stdout.flush() # ensures bar is displayed incrementally


en base a las respuestas anteriores y otras preguntas similares sobre la barra de progreso de CLI, creo que obtuve una respuesta general común para todas ellas. Compruébelo en https://.com/a/15860757/2254146

En resumen, el código es este:

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

Parece

Porcentaje: [##########] 99.0%


jajaja, acabo de escribir una cosita completa para esto, aquí está el código, ten en cuenta que no puedes usar Unicode cuando haces el bloque ASCII, uso cp437

import os import time def load(left_side, right_side, length, time): x = 0 y = "" print "/r" while x < length: space = length - len(y) space = " " * space z = left + y + space + right print "/r", z, y += "█" time.sleep(time) x += 1 cls()

y tu lo llamas asi

print "loading something awesome" load("|", "|", 10, .01)

asi se ve asi

loading something awesome |█████ |


y, solo para agregar a la pila, aquí hay un objeto que puedes usar

import sys class ProgressBar(object): DEFAULT_BAR_LENGTH = 65 DEFAULT_CHAR_ON = ''='' DEFAULT_CHAR_OFF = '' '' def __init__(self, end, start=0): self.end = end self.start = start self._barLength = self.__class__.DEFAULT_BAR_LENGTH self.setLevel(self.start) self._plotted = False def setLevel(self, level): self._level = level if level < self.start: self._level = self.start if level > self.end: self._level = self.end self._ratio = float(self._level - self.start) / float(self.end - self.start) self._levelChars = int(self._ratio * self._barLength) def plotProgress(self): sys.stdout.write("/r %3i%% [%s%s]" %( int(self._ratio * 100.0), self.__class__.DEFAULT_CHAR_ON * int(self._levelChars), self.__class__.DEFAULT_CHAR_OFF * int(self._barLength - self._levelChars), )) sys.stdout.flush() self._plotted = True def setAndPlot(self, level): oldChars = self._levelChars self.setLevel(level) if (not self._plotted) or (oldChars != self._levelChars): self.plotProgress() def __add__(self, other): assert type(other) in [float, int], "can only add a number" self.setAndPlot(self._level + other) return self def __sub__(self, other): return self.__add__(-other) def __iadd__(self, other): return self.__add__(other) def __isub__(self, other): return self.__add__(-other) def __del__(self): sys.stdout.write("/n") if __name__ == "__main__": import time count = 150 print "starting things:" pb = ProgressBar(count) #pb.plotProgress() for i in range(0, count): pb += 1 #pb.setAndPlot(i + 1) time.sleep(0.01) del pb print "done"

resultados en:

starting things: 100% [=================================================================] done

Esto generalmente se considera "exagerado", pero es útil cuando lo usas mucho



https://pypi.python.org/pypi/progressbar2/3.30.2

Progressbar2 es una buena biblioteca para ascii base progressbar para la línea de comandos tiempo de importación barra de progreso de importación

bar = progressbar.ProgressBar() for i in bar(range(100)): time.sleep(0.02) bar.finish()

https://pypi.python.org/pypi/tqdm

tqdm es una alternativa de progressbar2 y creo que se usa en pip3 pero no estoy seguro de eso

from tqdm import tqdm for i in tqdm(range(10000)): ...


Aquí hay un buen ejemplo de una barra de progreso escrita en Python: http://nadiana.com/animated-terminal-progress-bar-in-python

Pero si quieres escribirlo tú mismo. Podrías usar el módulo de curses para facilitar las cosas :)

[editar] Tal vez más fácil no es la palabra para maldiciones. Pero si quieres crear un cui completo, entonces Maldes se encarga de muchas cosas para ti.

[edit] Dado que el enlace anterior está muerto, he puesto mi propia versión de Python Progressbar, consígala aquí: https://github.com/WoLpH/python-progressbar


import sys def progresssbar(): for i in range(100): time.sleep(1) sys.stdout.write("%i/r" % i) progressbar()

NOTA: si ejecuta esto en el intérprete interactivo, obtendrá números adicionales impresos


import time,sys for i in range(100+1): time.sleep(0.1) sys.stdout.write((''=''*i)+(''''*(100-i))+("/r [ %d"%i+"% ] ")) sys.stdout.flush()

salida

[29%] ===================