Как написать индикатор прогресса загрузки в Python? - PullRequest
53 голосов
/ 09 сентября 2008

Я пишу небольшое приложение для загрузки файлов через http (как, например, описано здесь ).

Я также хочу включить небольшой индикатор прогресса загрузки, показывающий процент прогресса загрузки.

Вот что я придумал:

    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("\b\b\b")
      sys.stdout.flush()

Вывод: MyFileName ... 9%

Какие-нибудь другие идеи или рекомендации для этого?

Одна вещь, которая несколько раздражает, это мигающий курсор в терминале на первой цифре процента. Есть ли способ предотвратить это? Есть ли способ скрыть курсор?

EDIT:

Здесь лучшая альтернатива - использование глобальной переменной для имени файла в dlProgress и кода '\ 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()

Вывод: MyFileName ... 9%

И курсор появляется в конце строки. Гораздо лучше.

Ответы [ 9 ]

17 голосов
/ 09 сентября 2008

Есть библиотека текстового индикатора выполнения для Python на http://pypi.python.org/pypi/progressbar/2.2, которая может оказаться полезной:

Эта библиотека предоставляет индикатор выполнения в текстовом режиме. Это обычно используется для отображения хода выполнения длительной операции, обеспечивая визуальную подсказку о том, что обработка выполняется.

Класс ProgressBar управляет прогрессом, а формат строки задается рядом виджетов. Виджет - это объект, который может отображаться по-разному в зависимости от состояния процесса. Есть три типа виджетов: - строка, которая всегда показывает себя; - ProgressBarWidget, который может возвращать различное значение каждый раз, когда вызывается его метод обновления; и - ProgressBarWidgetHFill, который похож на ProgressBarWidget, за исключением того, что он расширяется, чтобы заполнить оставшуюся ширину линии.

Модуль ProgressBar очень прост в использовании, но очень мощный. И автоматически поддерживает такие функции, как автоматическое изменение размера при наличии.

15 голосов
/ 09 сентября 2008

Вы также можете попробовать:

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

Использование одиночного возврата каретки в начале строки, а не нескольких возвратов. Ваш курсор все еще будет мигать, но он будет мигать после знака процента, а не под первой цифрой, и с одним управляющим символом вместо трех вы можете получить меньше мерцания.

7 голосов
/ 16 марта 2016

Для чего это стоит, вот код, который я использовал, чтобы заставить его работать:

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) )
4 голосов
/ 09 сентября 2008

Если вы используете пакет curses, у вас будет гораздо больший контроль над консолью. Кроме того, он требует более высоких затрат на сложность кода и, вероятно, не нужен, если вы не разрабатываете большое консольное приложение.

Для простого решения вы всегда можете поставить вращающееся колесо в конец сообщения о статусе (последовательность символов |, \, -, /, которая на самом деле выглядит хорошо под мигающим курсором.

1 голос
/ 18 апреля 2017
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 голос
/ 02 января 2013

Я использовал этот код:

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()
0 голосов
/ 10 февраля 2015

Поздно на вечеринку, как обычно. Вот реализация, которая поддерживает отчетность о прогрессе, например, ядро ​​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 голосов
/ 14 октября 2012

Вот как я мог это сделать: https://github.com/mouuff/MouDownloader/blob/master/api/download.py

0 голосов
/ 01 апреля 2009

Для небольших файлов вам может понадобиться эта строка, чтобы избежать сумасшедших процентов:

sys.stdout.write ("\ r% 2d %%"% процентов)

sys.stdout.flush ()

Приветствия

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...