Texto barra de progreso en la consola [cerrada]
Pregunta
¿Hay una buena manera de hacer lo siguiente?
Me escribió una aplicación de consola sencilla para cargar y descargar archivos desde un servidor FTP usando el ftplib.
Cada vez algunos fragmentos de datos se descargan, quiero actualizar una barra de progreso de texto, incluso si es sólo un número.
Pero no quiero borrar todo el texto que ha sido impreso en la consola. (Haciendo un "claro" y luego imprimir el porcentaje actualizada).
Solución
Una simple y personalizable Barra de progreso
Aquí hay un agregado de muchas de las respuestas a continuación que utilizo regularmente (no hay importaciones requeridas).
# 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()
Nota: Esto es para Python 3; ver los comentarios para detalles sobre el uso de este en Python 2.
Uso de muestra
import time
# 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...
time.sleep(0.1)
# Update Progress Bar
printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', length = 50)
Salida de muestra:
Progress: |█████████████████████████████████████████████-----| 90.0% Complete
Actualizar
Hubo una discusión en los comentarios con respecto a una opción que permite que la barra de progreso para ajustar dinámicamente el ancho de ventana de terminal. Si bien no recomiendo esto, aquí hay un GIST que implementa esta característica (y las notas de las salvedades) .
Otros consejos
Escritura '\ r' se moverá la parte posterior cursor 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()
tqdm: añadir un indicador de progreso a sus bucles en un segundo :
>>> import time
>>> from tqdm import tqdm
>>> for i in tqdm(range(100)):
... time.sleep(1)
...
|###-------| 35/100 35% [elapsed: 00:35 left: 01:05, 1.00 iters/sec]
Escribir un \r
a la consola. Eso es un "retorno de carro", que hace que todo el texto después de que se hizo eco en el comienzo de la línea. Algo así como:
def update_progress(progress):
print '\r[{0}] {1}%'.format('#'*(progress/10), progress)
que le dará algo como: [ ########## ] 100%
Es menos de 10 líneas de código.
Lo esencial 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
clic librería escrita por el Mozart de Python, Armin Ronacher.
$ pip install click # both 2 and 3 compatible
Para crear una barra de progreso sencilla:
import click
with click.progressbar(range(1000000)) as bar:
for i in bar:
pass
Esto es lo que parece:
# [###-------------------------------] 9% 00:01:14
Personalizar contenido de su corazón:
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
aspecto personalizado:
(_(_)===================================D(_(_| 100000/100000 00:00:02
Hay aún más opciones, consulte la API docs :
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)
Me doy cuenta de que estoy tarde para el juego, pero aquí hay un poco de estilo Yum (Red Hat) que escribí (no va por el 100% de precisión aquí, pero si usted está utilizando una barra de progreso para ese nivel de precisión , entonces usted está 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 se mantienen estacionarios y aumentan sólo los hashes.
Esto podría funcionar mejor como decorador. Por otro día ...
Comprobar esta biblioteca: Clint
que tiene un montón de 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)
enlace ofrece un breve resumen de sus características
Este es un ejemplo agradable de un progressbar escrito en Python: http : //nadiana.com/animated-terminal-progress-bar-in-python
Pero si desea escribir usted mismo. Se podría utilizar el módulo curses
para facilitar las cosas:)
[editar] Tal vez más fácil no es la palabra de maldiciones. Pero si desea crear una cui en toda regla de maldiciones se ocupa de un montón de cosas para usted.
[editar] Desde el antiguo enlace está muerto He puesto mi propia versión de un Progressbar Python, obtenerlo aquí: https: //github.com/WoLpH/python-progressbar
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%] ===================
y, sólo para añadir a la pila, aquí es un objeto que puede utilizar
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 sería más comúnmente se considera que es "por encima", pero es muy útil cuando se está usando mucho
Ejecutar este en la línea de comandos de Python ( no en cualquier entorno IDE o desarrollo):
>>> 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.
Instalar tqdm
. (pip install tqdm
)
y utilizarlo como sigue:
import time
from tqdm import tqdm
for i in tqdm(range(1000)):
time.sleep(0.01)
Esto es una barra de progreso de 10 segundos que la producción'LL algo como esto:
47%|██████████████████▊ | 470/1000 [00:04<00:05, 98.61it/s]
- http://code.activestate.com/recipes/168639- barra de progreso de la clase / (2002)
- http://code.activestate.com/ recetas / 299207-consola de texto avances en indicadores de clase / (2004)
- http://pypi.python.org/pypi/progressbar (2006)
Y una gran cantidad de tutoriales en espera de ser buscado en Google.
Estoy utilizando el progreso de Reddit . Me gusta porque puedo imprimir progreso para todos los elementos de una línea, y no debería borrar las impresiones del programa.
Editar: enlace fijo
basado en las respuestas anteriores y otras preguntas similares acerca de la CLI barra de progreso, creo que tengo una respuesta general común a todos ellos. Comprobarlo en https://stackoverflow.com/a/15860757/2254146
En resumen, el código es el siguiente:
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()
Las apariencias como
Porcentaje: [##########] 99,0%
Le recomiendo usar tqdm - https://pypi.python.org/pypi/tqdm -. lo que hace que sea fácil de convertir cualquier iterable o proceso en una barra de progreso y maneja todas estas perder el tiempo con los terminales necesarios
A partir de la documentación: "tqdm puede soportar fácilmente las devoluciones de llamada / ganchos y actualizaciones manuales He aquí 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)
Trate de 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
import sys
def progresssbar():
for i in range(100):
time.sleep(1)
sys.stdout.write("%i\r" % i)
progressbar()
NOTA: si ejecuta esto en interepter interactiva te números adicionales imprimió
lol que acabo de escribir toda una cosita para este aquí está el mantener el código en cuenta que no puede utilizar Unicode cuando se hace el bloque ascii yo 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 se llame igual que
print "loading something awesome"
load("|", "|", 10, .01)
lo que parece que este
loading something awesome
|█████ |
Con los consejos grandes por encima de Trabajo fuera la barra de progreso.
Sin embargo, me gustaría señalar algunas deficiencias
-
Cada vez que se vacía la barra de progreso, que se iniciará en una nueva línea
print('\r[{0}]{1}%'.format('#' * progress* 10, progress))
así:
[] 0%
[#] 10%
[##] 20%
[###] 30%
2. El corchete ']' y el número ciento en el turno de mano derecha, como el '###' hacen más largos.
3. error Un ocurrirá si 'progreso / 10' la expresión no puede devolver un entero.
Y el código siguiente se solucionará el problema anterior.
def update_progress(progress, total):
print('\r[{0:10}]{1:>2}%'.format('#' * int(progress * 10 /total), progress), end='')
Una solución muy simple es poner este código en su bucle:
Ponga esto en el cuerpo (es decir, superior) de su archivo:
import sys
Ponga esto en el cuerpo de su bucle:
sys.stdout.write("-") # prints a dash for each iteration of loop
sys.stdout.flush() # ensures bar is displayed incrementally
Código para el pitón barra de progreso del terminal
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()
La elaboración de algunas de las ideas que encontrar aquí, y la adición de tiempo restante que queda:
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)
Bueno, aquí está el código que funciona y lo probaron antes de la publicación:
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:
- 20 barra de caracteres (1 carácter para cada 5 (número racional))
- caracteres de relleno personalizados
- Custom caracteres vacíos
- Halt (cualquier número por debajo de 0)
- Listo (100 y cualquier número por encima de 100)
- recuento Progreso (0-100 (por debajo y por encima utilizado para funciones especiales))
- Número Porcentaje junto al bar, y es una sola línea
Contras:
- Apoyos sólo enteros (que puede ser modificado para apoyarlos, sin embargo, al hacer la división de una división entera, por lo que acaba de cambiar a
prog2 = prog/5
prog2 = int(prog/5)
)
Aquí está mi solución 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 la cadena. Esto no funciona dentro de la ventana de CMD de Windows.
función de tallo verde 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()
El módulo de Python progressbar es una opción agradable. 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()
https://pypi.python.org/pypi/progressbar2/3.30.2
Progressbar2 es una biblioteca bueno para progressbar base de ASCII para la línea de comandos tiempo de importación progressbar 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 su uso en PIP3 pero no estoy seguro de eso
from tqdm import tqdm
for i in tqdm(range(10000)):
...
i escribió una progressbar 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 se puede ver, se tiene: longitud de la barra, prefijo y un sufijo, relleno, espacio, texto en bar en 100% (oncomp) y las fronteras
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)
a cabo en curso:
30% [###### ]
a cabo en completa:
100% [ done in 9 sec ]