如何使用带有 urlretrieve 的进度条模块

How to use progressbar module with urlretrieve

我的 pyhton3 脚本使用 urlretrieve 通过互联网下载大量图像,我想添加一个带有每次下载的 完成百分比 下载速度

progressbar module seems like a good solution, but although I've looked through their examplesexample4 似乎是正确的,我仍然不明白如何将它包装在 urlretrieve.

我想我应该添加第三个参数:

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

但是我该如何正确定义它呢?

钩子定义为:

urlretrieve(url[, filename[, reporthook[, data]]]) “第三个参数,如果存在的话,是一个将被调用的钩子函数 建立网络连接时一次,每个块后一次 之后阅读。钩子将传递三个参数;块数 到目前为止传输的数据块大小(以字节为单位)和文件的总大小。 第三个参数在没有 return 的旧 FTP 服务器上可能是 -1 响应检索请求的文件大小。 “

所以,你可以写一个hook如下:

# 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() 方法迭代响应。

其他答案中的建议对我来说没有超过 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)
        pbar.start()

    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)

我认为更好的解决方案是创建一个具有所有需要状态的 class

import progressbar

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())