Barre de progression du texte dans la Console [fermé]
Y a-t-il un bon moyen de faire ce qui suit?
J'ai écrit une application de console simple pour télécharger et télécharger des fichiers à partir d'un serveur FTP en utilisant le ftplib.
Chaque fois que des morceaux de données sont téléchargés, je veux mettre à jour une barre de progression de texte, même si c'est juste un nombre.
Mais je ne veux pas effacer tout le texte qui a été imprimé sur la console. (Faire un "effacer", puis imprimer le pourcentage mis à jour.)
30 réponses
Voici un agrégat de nombreuses réponses ci-dessous que j'utilise régulièrement.
# 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
L'écriture de '\ r ' ramènera le curseur au début de la ligne.
Affiche un compteur de pourcentage:
import time
import sys
for i in range(100):
time.sleep(1)
sys.stdout.write("\r%d%%" % i)
sys.stdout.flush()
Écrivez un \r
dans la console. C'est un "retour chariot" qui fait écho à tout le texte après au début de la ligne. Quelque chose comme:
def update_progress(progress):
print '\r[{0}] {1}%'.format('#'*(progress/10), progress)
, Qui vous donnera quelque chose comme: [ ########## ] 100%
Tqdm: ajoutez un progress meter à vos boucles en une seconde:
>>> 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]
C'est moins de 10 lignes de code.
L'essentiel ici: 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
Essayez la bibliothèquecliquez sur écrite par le Mozart de Python, Armin Ronacher.
$ pip install click # both 2 and 3 compatible
Pour créer une barre de progression simple:
import click
with click.progressbar(range(1000000)) as bar:
for i in bar:
pass
Voici à quoi il ressemble:
# [###-------------------------------] 9% 00:01:14
Personnalisez le contenu de votre cœur:
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
Look personnalisé:
(_(_)===================================D(_(_| 100000/100000 00:00:02
Il y a encore plus d'options, voir les documents 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)
Je me rends compte que je suis en retard au jeu, mais voici un style légèrement Miam (Red Hat) que j'ai écrit (pas pour 100% de précision ici, mais si vous utilisez une barre de progression pour ce niveau de précision, alors vous vous trompez de toute façon):
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()
Devrait produire quelque chose qui ressemble à ceci:
Percent: [############## ] 69%
... lorsque les parenthèses restent stationnaires et que seuls les hachages augmentent.
Cela pourrait mieux fonctionner en tant que décorateur. Pour un autre jour...
Vérifier cette bibliothèque: clint
, Il a beaucoup de fonctionnalités, y compris une barre de progression:
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)
Ce lien fournit un aperçu rapide de ses fonctionnalités
Voici un bel exemple d'une barre de progression écrite en Python: http://nadiana.com/animated-terminal-progress-bar-in-python
Mais si vous voulez l'écrire vous-même. Vous pouvez utiliser le module curses
pour faciliter les choses:)
[modifier] Peut-être plus facile n'est pas le mot pour malédictions. Mais si vous voulez créer un véritable cui que les malédictions prend soin de beaucoup de choses pour vous.
[modifier] Puisque l'ancien lien est mort j'ai mis en place ma propre version D'un Python Progressbar, obtenez-le ici: 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()
Sortie
[ 29% ] ===================
Et, pour ajouter à la pile, voici un objet que vous pouvez utiliser
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"
Résultats dans:
starting things:
100% [=================================================================]
done
Ce serait le plus souvent considéré comme "over the top", mais c'est pratique quand vous l'utilisez beaucoup
Exécutez ceci sur la ligne de commande Python (Pas dans un environnement IDE ou de développement):
>>> import threading
>>> for i in range(50+1):
... threading._sleep(0.5)
... print "\r%3d" % i, ('='*i)+('-'*(50-i)),
Fonctionne bien sur mon système Windows.
Installer tqdm
.(pip install tqdm
)
et de l'utiliser comme suit:
import time
from tqdm import tqdm
for i in tqdm(range(1000)):
time.sleep(0.01)
C'est une barre de progression de 10 secondes qui produira quelque chose comme ceci:
47%|██████████████████▊ | 470/1000 [00:04<00:05, 98.61it/s]
- http://code.activestate.com/recipes/168639-progress-bar-class/ (2002)
- http://code.activestate.com/recipes/299207-console-text-progress-indicator-class/ (2004)
- http://pypi.python.org/pypi/progressbar (2006)
Et beaucoup de tutoriels en attente d'être googlé.
J'utilise progrès de reddit . Je l'aime parce qu'il peut imprimer la progression pour chaque élément dans une ligne, et il ne devrait pas effacer les impressions du programme.
Modifier: lien fixe
Sur la base des réponses ci-dessus et d'autres questions similaires sur la barre de progression CLI, je pense que j'ai eu une réponse commune générale à tous. Vérifiez-le à https://stackoverflow.com/a/15860757/2254146
En résumé, le code est le suivant:
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()
Ressemble à
Pour Cent: [##########] 99.0%
Je recommande d'utiliser tqdm - https://pypi.python.org/pypi/tqdm - ce qui rend simple de transformer tout itérable ou processus en une barre de progression, et gère tous les problèmes avec les terminaux nécessaires.
De la documentation: "tqdm peut facilement prendre en charge les rappels/hooks et les mises à jour manuelles. Voici un exemple avec 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)
import sys
def progresssbar():
for i in range(100):
time.sleep(1)
sys.stdout.write("%i\r" % i)
progressbar()
Remarque: Si vous exécutez ceci dans interepter interactif, vous obtenez des numéros supplémentaires imprimés
Lol je viens d'écrire un truc entier pour cela voici le code gardez à l'esprit que vous ne pouvez pas utiliser unicode lorsque vous faites bloc ascii j'utilise 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()
Et vous l'appelez comme
print "loading something awesome"
load("|", "|", 10, .01)
Donc ça ressemble à ceci
loading something awesome
|█████ |
Avec les grands conseils ci-dessus, je travaille sur la barre de progression.
Cependant, je voudrais souligner quelques lacunes
-
Chaque fois que la barre de progression est vidée, elle démarre sur une nouvelle ligne
print('\r[{0}]{1}%'.format('#' * progress* 10, progress))
Comme ceci:
[] 0%
[#]10%
[##]20%
[###]30%
2.Le support carré'] 'et le nombre de pourcentage sur le côté droit se déplacent à droite lorsque le' # # # ' s'allonge.
3. Une erreur se produira si l'expression 'progress / 10' impossible de retourner un entier.
Et le code suivant résoudra le problème ci-dessus.
def update_progress(progress, total):
print('\r[{0:10}]{1:>2}%'.format('#' * int(progress * 10 /total), progress), end='')
Code pour la barre de progression du terminal 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()
Rassembler quelques-unes des idées que j'ai trouvées ici, et ajouter le temps estimé restant:
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)
Essayez d'installer ce paquet: 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
Une solution très simple est de mettre ce code dans votre boucle:
Mettez ceci dans le corps (c'est à dire en haut) de votre fichier:
import sys
Mettez ceci dans le corps de votre boucle:
sys.stdout.write("-") # prints a dash for each iteration of loop
sys.stdout.flush() # ensures bar is displayed incrementally
Eh Bien voici le code qui fonctionne et je l'ai testé avant de poster:
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()
Avantages:
- barre de 20 caractères (1 caractère pour chaque 5 (Nombre Sage))
- caractères de remplissage personnalisés
- caractères vides personnalisés
- Arrêter (tout nombre inférieur à 0)
- fait (100 et tout nombre supérieur à 100)
- Nombre de progrès (0-100 (ci-dessous et ci-dessus utilisés pour les fonctions spéciales))
- Nombre de pourcentage à côté de la barre, et c'est un seul ligne
Inconvénients:
- ne supporte que les entiers (il peut être modifié pour les supporter, en faisant de la division une division entière, alors changez simplement
prog2 = prog/5
enprog2 = int(prog/5)
)
Voici ma solution Python 3:
import time
for i in range(100):
time.sleep(1)
s = "{}% Complete".format(i)
print(s,end=len(s) * '\b')
' \ b ' est une barre oblique inverse, pour chaque caractère de votre chaîne. Cela ne fonctionne pas dans la fenêtre cmd de Windows.
Fonction de Greenstick pour 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()
Le module python progressbar est un bon choix. Voici mon code typique:
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 est une bonne bibliothèque pour la base ASCII progressbar pour la ligne de commande le délai d'importation importer progressbar
bar = progressbar.ProgressBar()
for i in bar(range(100)):
time.sleep(0.02)
bar.finish()
Https://pypi.python.org/pypi/tqdm
Tqdm est une alternative de progressbar2 et je pense qu'il est utilisé dans pip3 mais je ne suis pas sûr de cela
from tqdm import tqdm
for i in tqdm(range(10000)):
...
, j'ai écrit une barre de progression 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)
Comme vous pouvez le voir, il a: longueur de la barre, préfixe et Suffixe, remplissage, espace, texte en barre sur 100%(oncomp) et bordures
Voici un exemple:
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 cours:
30% [###### ]
Terminé:
100% [ done in 9 sec ]