#1 Le 25/06/2008, à 18:47
- Pistolero
[Python] Barre de progression ASCII pour shell
Salut,
ca fait un petit moment que j'ai ecrit un petit bon de code pour avoir une barre de progression dans le shell, qui ressemble a ca:
Title [============ ] 21 %
je l'utilise pratiquement tous les jours, car des que je fais tourner un prog en python je rajoute ma barre, car c'est bien sympa d'avoir l'etat d'avancement dans le shell surtout quand certain algo sont un peu long.
Bref, le truc c'est que j'avais ecrit ca a la va-vite, et cette barre n'est pas parfaite. On voit apparaitre le curseur clignoter a differents endroits de la barre a cause de la mise a jour du texte.
Comment ameliorer son esthetisme, je sais mettre des couleurs pour les sorties shell mais par rapport aussi a la structure et a la methode de la mise a jours.
class ProgressBar:
'''
Progress bar
'''
def __init__ (self, valmax, maxbar, title):
if valmax == 0: valmax = 1
if maxbar > 200: maxbar = 200
self.valmax = valmax
self.maxbar = maxbar
self.title = title
def update(self, val):
import sys
# format
if val > self.valmax: val = self.valmax
# process
perc = round((float(val) / float(self.valmax)) * 100)
scale = 100.0 / float(self.maxbar)
bar = int(perc / scale)
# render
out = '\r %20s [%s%s] %3d %%' % (self.title, '=' * bar, ' ' * (self.maxbar - bar), perc)
sys.stdout.write(out)
avec valmax la valeur maxi de la variable qu'on observe, maxbar la valeur maxi de la taille de la bar en nombre de caracteres et title bah... le titre. Elle s'utilise comme cela:
Bar = ProgressBar(100, 60, 'MonTitre')
for i in xrange(100):
Bar.update(i)
Voila, des idees, des suggestions, tout en restant simple, de telle sorte a eviter les 1000 lignes de code pour une barre de progession .
A+
Dernière modification par Pistolero (Le 25/06/2008, à 18:48)
Desole pour les accents, je suis esclave d'un qwerty.
Hors ligne
#2 Le 21/04/2009, à 15:15
- s@mson
Re : [Python] Barre de progression ASCII pour shell
Bonjour,
http://pypi.python.org/pypi/progressbar/2.2
Elle est pas belle la vie? :-)
Dernière modification par s@mson (Le 21/04/2009, à 15:15)
Hors ligne
#3 Le 21/04/2009, à 16:47
- HP
Re : [Python] Barre de progression ASCII pour shell
Je vais, peut-être, suivre ce topic… ou pas
cat /dev/urandom >/dev/null 2>&1 #github
Hors ligne
#4 Le 03/02/2010, à 16:58
- Narann
Re : [Python] Barre de progression ASCII pour shell
Merci beaucoup Pistolero pour ce script! Ça parait bête mais c'est impossible à trouver ce genre de truc! Merci Merci Merci!
Hors ligne
#5 Le 28/10/2010, à 08:43
- elendil
Re : [Python] Barre de progression ASCII pour shell
Génial ça fait longtemps que je cherchais quelque chose du genre !
J'ai modifié ton code comme il suit :
class ProgressBar:
'''
Progress bar
'''
def __init__ (self, valmax, maxbar, title):
if valmax == 0: valmax = 1
if maxbar > 200: maxbar = 200
self.valmax = valmax
self.maxbar = maxbar
self.title = title
def update(self, val):
import sys
# process
perc = round((float(val) / float(self.valmax)) * 100)
scale = 100.0 / float(self.maxbar)
bar = int(perc / scale)
# render
out = '\r %20s [%s%s] %3d %%' % (self.title, '=' * bar, ' ' * (self.maxbar - bar), perc)
sys.stdout.write(out)
sys.stdout.flush()
J'ai rajouté sys.stdout.flush() ce qui permet de vider le buffer car chez moi je n'avait la barre de progression qu'une fois la boucle finie (source : topic)
J'ai supprimé la ligne :
if val > self.valmax: val = self.valmax
Car je trouve intéressant de savoir si ma boucle plante et dépasse la valeur maximale !
En effet si j'entre une valeur max égale à 100 et que dans mon code ma boucle dépasse cette valeur, la barre de progression affiche 100% 100% 100% . . . etc Je préfère avoir 110%, 120% . . . Du coup je comprend où est l'erreur !
Une autre solution serait de mettre :
if val > self.valmax: raise ValueError("'val' dépasse 'valmax')
Dernière modification par elendil (Le 28/10/2010, à 08:53)
Hors ligne
#6 Le 28/10/2010, à 19:36
- kidanger
Re : [Python] Barre de progression ASCII pour shell
Bonjour,
Je trouve le "import sys" un peu mal placé, ne serait il pas mieux en dehors de la classe ?
De plus, je remplacerais
if valmax == 0: valmax = 1
if maxbar > 200: maxbar = 200
self.valmax = valmax
self.maxbar = maxbar
par EDIT: ce qui suit est faux...
self.valmax = min(1, valmax)
self.maxbar = max(maxbar, 200)
C'est du chipotage, ça doit pas changer grand chose en performance
En tout cas, merci pour cette classe, bien légère mais qui peut être utile.
Dernière modification par kidanger (Le 29/10/2010, à 15:54)
Hors ligne
#7 Le 29/10/2010, à 14:42
- elendil
Re : [Python] Barre de progression ASCII pour shell
Je suppose que tu veux dire :
self.valmax = max(1, valmax)
self.maxbar = min(maxbar, 200)
Et encore dans ce cas ton code n'est pas équivalent à celui donné par Pistolero car 'self.valmax = max(1, valmax)' va renvoyer 1 pour toute valeur inférieure à 1. Or Pistolero veut avoir 1 uniquement lorsque valmax = 0.
Je me trompe ?
Dernière modification par elendil (Le 29/10/2010, à 14:47)
Hors ligne
#8 Le 29/10/2010, à 15:51
- kidanger
Re : [Python] Barre de progression ASCII pour shell
Je suppose que tu veux dire :
self.valmax = max(1, valmax) self.maxbar = min(maxbar, 200)
Et encore dans ce cas ton code n'est pas équivalent à celui donné par Pistolero car 'self.valmax = max(1, valmax)' va renvoyer 1 pour toute valeur inférieure à 1. Or Pistolero veut avoir 1 uniquement lorsque valmax = 0.
Je me trompe ?
J'ai encore écrit trop vite...
Par contre, j'ai pas testé le script, mais si valmax est inférieur à 0, ça marche encore ? (Ah, le 0 ça doit être pour éviter la division...)
La prochaine fois je réfléchirais à 3 fois avant de poster...
Hors ligne
#9 Le 29/10/2010, à 16:07
- elendil
Re : [Python] Barre de progression ASCII pour shell
Ça m'arrive tellement souvent (d'écrire lus vite que je réfléchis . . . )
J'ai testé le code et j'ai apporté d'autres modifications mais je ne les aies pas sous la main. Je les poste prochainement !
Hors ligne
#10 Le 03/03/2015, à 16:12
- pythonTim
Re : [Python] Barre de progression ASCII pour shell
Hello
je l'ai un peu amélioré
Fonctionne sous Debian.Linux
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import os
import time
class ProgressBar:
'''
Progress bar
'''
def __init__ (self, valmax, maxbar, title):
if valmax == 0: valmax = 1
if maxbar > 200: maxbar = 200
self.valmax = valmax
self.maxbar = maxbar
self.title = title
def update(self, val):
# format
if val > self.valmax: val = self.valmax
# process
perc = round((float(val) / float(self.valmax)) * 100)
scale = 100.0 / float(self.maxbar)
bar = int(perc / scale)
# render
out = '\r%20s [%s%s] %3d %% ' % (self.title, '=' * bar, ' ' * (self.maxbar - bar), perc)
sys.stdout.write(out)
#Extinction du curseur
os.system('setterm -cursor off')
#Rafraichissement de la barre
sys.stdout.flush()
## Test =
i = 1 #Variable surveillée
#Objet barre de progression
barre = ProgressBar(60,42, "chargement")
print'\n'
for x in range(60):
barre.update(i)
time.sleep(0.30)
i = i+1
#Redemarrage du curseur
os.system('setterm -cursor on')
print'\n'
Dernière modification par pythonTim (Le 05/03/2015, à 18:40)
Hors ligne
#11 Le 25/06/2015, à 06:15
- texom512
Re : [Python] Barre de progression ASCII pour shell
Je l'ai encore amélioré !
__author__ = 'texom512'
import sys
import time
from math import *
class ProgressBar:
"""
This class allows you to make easily a progress bar.
"""
def __init__(self, steps, maxbar=100, title='Chargement'):
if steps <= 0 or maxbar <= 0 or maxbar > 200:
raise ValueError
self.steps = steps
self.maxbar = maxbar
self.title = title
self.perc = 0
self._completed_steps = 0
self.update(False)
def update(self, increase=True):
if increase:
self._completed_steps += 1
self.perc = floor(self._completed_steps / self.steps * 100)
if self._completed_steps > self.steps:
self._completed_steps = self.steps
steps_bar = floor(self.perc / 100 * self.maxbar)
if steps_bar == 0:
visual_bar = self.maxbar * ' '
else:
visual_bar = (steps_bar - 1) * '=' + '>' + (self.maxbar - steps_bar) * ' '
sys.stdout.write('\r' + self.title + ' [' + visual_bar + '] ' + str(self.perc) + '%')
sys.stdout.flush()
if __name__ == '__main__':
bar = ProgressBar(50)
i = 0
while bar.perc != 100:
bar.update()
time.sleep(0.5)
i += 1
Cette nouvelle version présente de nombreux avantages par rapport à l'ancienne :
- Fonctionne avec Python 3.
- La bar s'affiche dès l'instant où on déclare notre variable.
- La bar est affiché vide au tout début.
- La bar se termine à 100% et pas à 99%
- La bar n'affiche qu'une fois les 100%
- Plus besoin de paramètre pour la méthode update.
- Il y a une flèche pour le chargement, pas juste des signes "=".
- Le pourcentage est un attribut, il est donc accessible depuis l'extérieur de la classe.
- Le code est plus propre qu'avant.
Dernière modification par texom512 (Le 16/01/2016, à 11:35)
Hors ligne