Как использовать модуль progressbar с urlretrieve

97
8

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

Модуль progressbar выглядит как хорошее решение, но, хотя я просмотрел их примеры, и example4 кажется правильным, я все еще не могу понять, как обернуть его вокруг urlretrieve.

Думаю, я должен добавить третий параметр:

urllib.request.urlretrieve('img_url', 'img_filename', some_progressbar_based_reporthook)

Но как я правильно его определяю?

спросил(а) 2021-01-19T14:53:15+03:00 2 месяца, 3 недели назад
1
Решение
87

Крюк определяется как:

urlretrieve(url[, filename[, reporthook[, data]]]) "Третий аргумент, если присутствует, - это функция перехвата, которая будет вызываться один раз при установлении сетевого соединения и после каждого последующего чтения блока. передаются три аргумента: количество блоков, переданных до сих пор, размер блока в байтах и общий размер файла. Третий аргумент может быть -1 на старых FTP-серверах, которые не возвращают размер файла в ответ на запрос поиска ".

Итак, вы можете написать крючок следующим образом:

# Global variables
pbar = None
downloaded = 0

def show_progress(count, block_size, total_size):
if pbar is None:
pbar = ProgressBar(maxval=total_size)

downloaded += block_size
pbar.update(block_size)
if downloaded == total_size:
pbar.finish()
pbar = None
downloaded = 0

В качестве примечания я настоятельно рекомендую вам использовать библиотеку запросов, которая намного проще в использовании, и вы можете перебирать ответ с помощью iter_content().

ответил(а) 2021-01-19T14:53:15+03:00 2 месяца, 3 недели назад
87

Предложение в другом ответе для меня не прогрессировало 1%. Вот полная реализация, которая работает для меня на Python 3:


import progressbar
import urllib.request

pbar = None

def show_progress(block_num, block_size, total_size):
global pbar
if pbar is None:
pbar = progressbar.ProgressBar(maxval=total_size)

downloaded = block_num * block_size
if downloaded < total_size:
pbar.update(downloaded)
else:
pbar.finish()
pbar = None

urllib.request.urlretrieve(model_url, model_file, show_progress)

ответил(а) 2021-01-19T14:53:15+03:00 2 месяца, 3 недели назад
75

Я думаю, что лучшее решение состоит в том, чтобы создать класс, который имеет все необходимое состояние

class MyProgressBar():
def __init__(self):
self.pbar = None

def __call__(self, block_num, block_size, total_size):
if not self.pbar:
self.pbar=progressbar.ProgressBar(maxval=total_size)
self.pbar.start()

downloaded = block_num * block_size
if downloaded < total_size:
self.pbar.update(downloaded)
else:
self.pbar.finish()

и позвоните:

urllib.request.urlretrieve('img_url', 'img_filename', MyProgressBar())

ответил(а) 2021-01-19T14:53:15+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема