Comment écrire un indicateur de progression de téléchargement en Python?

J'écris une petite application pour télécharger des fichiers sur http (comme, par exemple, décrit ici).

Je veux aussi inclure un petit indicateur de progression du téléchargement indiquant le pourcentage de progression du téléchargement.

Voici ce que je suis venu avec:

    sys.stdout.write(rem_file + "...")    
    urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress)

    def dlProgress(count, blockSize, totalSize):
      percent = int(count*blockSize*100/totalSize)
      sys.stdout.write("%2d%%" % percent)
      sys.stdout.write("bbb")
      sys.stdout.flush()

Sortie: Monfichier... 9%

D'autres idées ou recommandations pour le faire?

Une chose qui est quelque peu agaçante est le curseur clignotant dans le terminal sur le premier chiffre du pourcentage. Est-il un moyen pour éviter cela? Est-il un moyen de masquer le curseur?

Modifier:

Voici une meilleure alternative en utilisant une variable globale pour le nom de fichier dans dlProgress et le code 'r':

    global rem_file # global variable to be used in dlProgress

    urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress)

    def dlProgress(count, blockSize, totalSize):
      percent = int(count*blockSize*100/totalSize)
      sys.stdout.write("r" + rem_file + "...%d%%" % percent)
      sys.stdout.flush()

Sortie: Monfichier...9%

Et le curseur apparaît à la fin de la ligne. Beaucoup mieux.

50
demandé sur Community 2008-09-09 08:09:15

9 réponses

Il y a une bibliothèque de barre de progression de texte pour python à http://pypi.python.org/pypi/progressbar/2.2 que vous pourriez trouver utile:

Cette bibliothèque fournit une barre de progression en mode texte. Ceci est généralement utilisé pour afficher la progression d'une opération de longue durée, fournissant un indice visuel que le traitement est en cours.

La classe ProgressBar gère la progression, et le format de la ligne est donné par un certain nombre de widgets. Un widget est un objet qui peut afficher diferently selon l'état des progrès. Il existe trois types de widget: - une chaîne, qui s'affiche toujours; - un ProgressBarWidget, qui peut renvoyer une valeur différente chaque fois que sa méthode de mise à jour est appelée; et - un ProgressBarWidgetHFill, qui est comme ProgressBarWidget, sauf qu'il se développe pour remplir la largeur restante de la ligne.

Le module progressbar est très facile à utiliser, mais très puissant. Et prend automatiquement en charge des fonctionnalités telles que le redimensionnement automatique lorsque disponible.

17
répondu Readonly 2008-09-09 04:48:28

Vous pouvez aussi essayer:

sys.stdout.write("\r%2d%%" % percent)
sys.stdout.flush()

En utilisant un seul retour chariot au début de votre chaîne plutôt que plusieurs espaces arrière. Votre curseur clignote toujours, mais il clignote après le signe de pourcentage plutôt que sous le premier chiffre, et avec un caractère de contrôle au lieu de trois, Vous pouvez obtenir moins de scintillement.

15
répondu Commodore Jaeger 2008-09-09 04:21:09

Pour ce que ça vaut, voici le code que j'ai utilisé pour le faire fonctionner:

from urllib import urlretrieve
from progressbar import ProgressBar, Percentage, Bar

url = "http://......."
fileName = "file"
pbar = ProgressBar(widgets=[Percentage(), Bar()])
urlretrieve(url, fileName, reporthook=dlProgress)

def dlProgress(count, blockSize, totalSize):
    pbar.update( int(count * blockSize * 100 / totalSize) )
6
répondu tstone2077 2016-10-17 13:34:20

Si vous utilisez le paquet curses, Vous avez beaucoup plus de contrôle sur la console. Il a également un coût plus élevé dans la complexité du code et est probablement inutile, sauf si vous développez une grande application basée sur la console.

Pour une solution simple, vous pouvez toujours mettre le Rouet à la fin du message d'état (la séquence de caractères |, \, -, / qui semble en fait agréable sous le curseur clignotant.

4
répondu hazzen 2008-09-09 04:14:37

J'ai utilisé ce code:

url = (<file location>)
file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)

file_size_dl = 0
block_sz = 8192
while True:
    buffer = u.read(block_sz)
    if not buffer:
        break

    file_size_dl += len(buffer)
    f.write(buffer)
    status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
    status = status + chr(8)*(len(status)+1)
    print status,

f.close()
1
répondu MichaelvdNet 2013-01-02 14:01:43
def download_progress_hook(count, blockSize, totalSize):
  """A hook to report the progress of a download. This is mostly intended for users with slow internet connections. Reports every 5% change in download progress.
  """
  global last_percent_reported
  percent = int(count * blockSize * 100 / totalSize)

  if last_percent_reported != percent:
    if percent % 5 == 0:
      sys.stdout.write("%s%%" % percent)
      sys.stdout.flush()
    else:
      sys.stdout.write(".")
      sys.stdout.flush()

    last_percent_reported = percent

urlretrieve(url, filename, reporthook=download_progress_hook)
1
répondu Paal Pedersen 2017-04-18 14:43:56

Pour les petits fichiers, vous devrez peut-être avoir ces lignes afin d'éviter les pourcentages fous:

Sys.la sortie standard stdout.Ecrire ("\r % 2d%%"%%)

Sys.la sortie standard stdout.flush ()

Santé

0
répondu 2009-04-01 10:04:19

C'est comme ça que j'ai fait cela pourrait vous aider: https://github.com/mouuff/MouDownloader/blob/master/api/download.py

0
répondu mou 2012-10-14 08:31:23

En retard à la fête, comme d'habitude. Voici une implémentation qui prend en charge le reporting des progrès, comme le core urlretrieve:

import urllib2

def urlretrieve(urllib2_request, filepath, reporthook=None, chunk_size=4096):
    req = urllib2.urlopen(urllib2_request)

    if reporthook:
        # ensure progress method is callable
        if hasattr(reporthook, '__call__'):
            reporthook = None

        try:
            # get response length
            total_size = req.info().getheaders('Content-Length')[0]
        except KeyError:
            reporthook = None

    data = ''
    num_blocks = 0

    with open(filepath, 'w') as f:
        while True:
            data = req.read(chunk_size)
            num_blocks += 1
            if reporthook:
                # report progress
                reporthook(num_blocks, chunk_size, total_size)
            if not data:
                break
            f.write(data)

    # return downloaded length
    return len(data)
0
répondu mafrosis 2015-02-10 04:38:33