Créer une barre de progression en Python

Denis Hulo

Objectif : créer une barre de progression avec tqdm pour suivre l'avancement de l'exécution de votre code Python.

Niveau requis : débutant

Commentez cet article : Commentez

- Titre : Créer une barre de progression en Python

- Auteur : Denis Hulo

- Parution : 16 octobre 2024

- Public visé :

- Licence : Copyright ® 2024 Denis Hulo. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Installation de la bibliothèque tqdm

- III. Exemples de mise en œuvre

- III-A. Enveloppage d'un itérable

- III-B. Méthode update

- IV. Application : progression d'une série de tests de primalité

- IV-A. Enveloppage d'un itérable

- IV-B. Méthode update

- V. Module Python

- VI. Conclusion

- VII. Téléchargement

- VIII. Remerciements

I - Introduction

Une barre de progression de texte est généralement utilisée pour afficher la progression d'une opération de longue durée, fournissant un signal visuel indiquant que le traitement est en cours.

La bibliothèque tqdm est très facile à utiliser pour afficher ce type de barre de progression dans une console Windows, dans une interface graphique (GUI), et même dans les notebooks IPython/Jupiter. Elle fonctionne sur les principales plateformes comme Linux, Windows et Mac.

Après avoir montré comment installer le module tqdm, on va donner quelques exemples simples de mise en œuvre, puis un cas pratique consistant à suivre la progression d'une série de tests de primalité effectués sur des nombres entiers. Ce module va également nous permettre de mesurer le temps d'exécution de notre code.

II - Installation de la bibliothèque tqdm

Elle peut s'installer avec pip en tapant simplement en ligne de commande : pip install tqdm.

III - Exemples de mise en œuvre

Il existe de nombreuses façons d'utiliser la bibliothèque tqdm, on donne pour commencer quelques exemples simples.

III-A - Enveloppage d'un itérable

On enveloppe tout d'abord une séquence de nombres entiers avec tqdm(range(100)) afin de suivre la progression sur ces nombres :

from tqdm import tqdm
import time

print("III. Mise en œuvre de barres de progression : exemples simples\n")
print("III-A. Exemple n°1 : enveloppage d'un itérable ..\n")

for i in tqdm(range(100)):
# pause de 0.1 sec.
time.sleep(0.1)

L'exécution du code affiche dans la console Windows :

Barre de progression : exemple n°1

Par défaut, on obtient en plus de la barre de progression, des informations telles que le pourcentage, le temps écoulé, le temps restant estimé (ETA) et même le nombre d'itérations par seconde.

L'éditeur IDLE de Python ne prend pas du tout en charge ce type de barre de progression.

III-B - Méthode update

Dans cet autre exemple on utilise cette fois la méthode update d'un objet tqdm représentant une barre de progression :

from tqdm import tqdm
import time

print("III. Mise en œuvre de barres de progression : exemples simples\n")
print("III-B. Exemple n°2 : méthode update ..\n")

# création de l'objet tqdm avec l'instruction with
with tqdm(total=100) as bar:
for i in range(100):
# pause de 0.1 sec.
time.sleep(0.1)

# mise à jour de la barre de progression : incrémente de 1 le compteur d'itérations
bar.update(1)

L'objet bar créé avec l'instruction with est appelé un objet de contexte. La méthode __enter__ est appelée au début du bloc with, et la méthode __exit__ est appelée à la fin. L'instruction with simplifie la gestion des ressources en garantissant que les opérations d'initialisation et de finalisation sont effectuées de manière cohérente et fiable.

Le code affiche dans la console Windows :

Barre de progression : exemple n°2

IV - Application : progression d'une série de tests de primalité

On souhaite maintenant suivre la progression d'une série de tests de primalité effectués sur des nombres entiers, l'objectif étant de déterminer la proportion de nombres premiers parmi cette séquence d'entiers. On va également en profiter pour mesurer le temps d'exécution de cette opération.

IV-A - Enveloppage d'un itérable

On enveloppe donc à nouveau un itérable à savoir une liste de nombres entiers en indiquant également la valeur maxi de la barre de progression (paramètre total) :

from tqdm import tqdm
import time

print("IV. Application : progression d'une série de tests de primalité\n")
print("IV-A. Exemple n°1 : enveloppage d'un itérable ..\n")

# initialisation du compteur de tests positifs
cpt = 0

# heure Unix de début (exprimée en secondes)
start = time.time()

# enveloppage de la liste de nombres entiers renvoyée par range(1, 1000001) :
# parcours des 1 000 000 de nombres entiers : 1 -> 1 000 0000
for N in tqdm(range(1, 1000001), total=1000000):
# test de primalité pour N
est_premier = test_primalite(N)

if est_premier: # si le test est positif
cpt+=1 # incrémentation du compteur

# heure Unix de fin (exprimée en secondes)
end = time.time()

print()

# Affiche la durée d'exécution.
print(f"Durée d'exécution : {end - start} sec.\n")

print("Proportion de nombres premiers :" , cpt/1000000)

La fonction de test de primalité est présente dans le module disponible en téléchargement à la fin de l'article.

L'exécution du code affiche dans la console Windows :

Progression d'une série de tests de primalité

On obtient à nouveau en plus de la barre de progression, des informations comme le pourcentage, le temps écoulé, le temps restant estimé (ETA) et même le nombre d'itérations par seconde.

IV-B - Méthode update

On utilise maintenant la méthode update d'un objet tqdm en prenant soin aussi d'indiquer la valeur maxi de la barre de progression :

from tqdm import tqdm
import time

print("IV. Application : progression d'une série de tests de primalité\n")
print("IV-B. Exemple n°2 : méthode update ..\n")

# initialisation du compteur de tests positifs
cpt = 0

# création de l'objet tqdm avec l'instruction with
with tqdm(total=1000000) as bar:

# parcours des 1 000 0000 de nombres entiers : 1 -> 1000000
for N in range(1, 1000001):

# test classique pour N
est_premier = test_primalite(N)

if est_premier: # si le test est positif
cpt+=1 # incrémentation du compteur

# mise à jour de la barre de progression : incrémente de 1 le compteur d'itérations
bar.update(1)

# durée d'exécution du code en secondes
duree = bar.format_dict['elapsed']

print()

# Affiche la durée d'exécution.
print(f"Durée d'exécution : {duree} sec.\n")

print("Proportion de nombres premiers :" , cpt/1000000)

Là encore, l'objet bar est créé avec l'instruction with simplifiant ainsi la gestion des ressources. On utilise cette fois l'attribut format_dict de l'objet bar et plus précisément la valeur de format_dict['elapsed'] pour connaître le temps d'exécution du bloc with.

L'exécution du code affiche dans la console Windows :

Progression d'une série de tests de primalité

La mise à jour de la barre de progression peut ralentir légèrement l'exécution du code. C'est pourquoi il peut être intéressant d'espacer ces mises à jour en utilisant le paramètre mininterval réglé par défaut à 0.1 sec.

Si vous souhaitez en savoir plus sur le module tqdm je vous invite à consulter cette documentation.

V - Module Python

On donne pour finir le code complet du module pour effectuer les différents tests :

from tqdm import tqdm
import time
import math

def test_primalite(N):
# fonction permettant de tester si N est premier en utilisant la méthode naïve
# N : nombre entier à tester

if N==1: return False # 1 n'est pas un nombre premier

# détermination du dernier entier m à tester comme diviseur de N : m est égal à la partie entière de √𝑁
m = int(math.sqrt(N))

# parcours des entiers : 2 -> m
for i in range(2, m+1):
# Si i divise N
if N % i == 0:
# N possède un diviseur donc n'est pas premier
# renvoie le tuple False => est_premier
return False

# N n'a pas de diviseur autre que 1 et lui-même, il est donc premier.
# renvoie True => est_premier
return True

print(test_primalite(1))

print("III. Mise en œuvre de barres de progression : exemples simples\n")
print("III-A. Exemple n°1 : enveloppage d'un itérable ..\n")

for i in tqdm(range(100)):
# pause de 0.1 sec.
time.sleep(0.1)

print(); print()

print("III-B. Exemple n°2 : méthode update ..\n")

# création de l'objet tqdm avec l'instruction with
with tqdm(total=100) as bar:
for i in range(100):
# pause de 0.1 sec.
time.sleep(0.1)

# mise à jour de la barre de progression : incrémente de 1 le compteur d'itérations
bar.update(1)

print(); print()

wait = input("Appuyer sur la touche Entrée pour continuer..")

print(); print()

print("IV. Application : progression d'une série de tests de primalité\n")
print("IV-A. Exemple n°1 : enveloppage d'un itérable ..\n")

# initialisation du compteur de tests positifs
cpt = 0

# heure Unix de début (exprimée en secondes)
start = time.time()

# enveloppage de la liste de nombres entiers renvoyée par range(1, 1000001) :
# parcours des 1 000 000 de nombres entiers : 1 -> 1000000
for N in tqdm(range(1, 1000001), total=1000000):

# test de primalité pour N
est_premier = test_primalite(N)

if est_premier: # si le test est positif
cpt+=1 # incrémentation du compteur

# heure Unix de fin (exprimée en secondes)
end = time.time()

print()

# Affiche la durée d'exécution.
print(f"Durée d'exécution : {end - start} sec.\n")

print("Proportion de nombres premiers :" , cpt/1000000)

print(); print()

print("IV-B. Exemple n°2 : méthode update ..\n")

# initialisation du compteur de tests positifs
cpt = 0

# création de l'objet tqdm avec l'instruction with
with tqdm(total=1000000) as bar:

# parcours des 1 000 0000 de nombres entiers : 1 -> 1000000
for N in range(1, 1000001):

# test de primalité pour N
est_premier = test_primalite(N)

if est_premier: # si le test est positif
cpt+=1 # incrémentation du compteur

# mise à jour de la barre de progression : incrémente de 1 le compteur d'itérations
bar.update(1)

# durée d'exécution du code en secondes
duree = bar.format_dict['elapsed']

print()

# Affiche la durée d'exécution.
print(f"Durée d'exécution : {duree} sec.\n")

print("Proportion de nombres premiers :" , cpt/1000000)

print()

wait = input("")

Vous pouvez enregistrer ce code dans un fichier d'extension .py ou bien récupérer celui disponible en téléchargement, puis en double-cliquant dessus vous devriez voir afficher dans la console Windows ce type de résultat :

Progression des tests

La vitesse de progression de la série de tests de primalité dépend bien sûr aussi de la puissance de calcul de votre machine.

VI - Conclusion

Après avoir donné quelques exemples de mise en œuvre de barres de progression à l'aide du package tqdm, on a pu montrer comment utiliser ce module pour suivre l'avancement d'une série de tests de primalité effectués sur des nombres entiers. Si vous souhaitez afficher la progression d'une opération de longue durée, vous pourrez facilement adapter ce code à vos besoins.

VII - Téléchargement

Le fichier compressé contenant le module Python pour effectuer les différents tests.

VIII - Remerciements

Je tiens à remercier Malick pour le suivi de cet article, ainsi que ALT pour sa relecture.

Sources

- Documentation & téléchargement de tqdm

- Description, installation & téléchargement de tqdm

- Définition d'un itérable

- Documentation sur l'instruction with

- Autre documentation sur l'instruction with

- Page Wikipedia sur l'ETA

- Page Wikipedia sur le test de primalité