Python urllib2 进度挂钩

Posted

技术标签:

【中文标题】Python urllib2 进度挂钩【英文标题】:Python urllib2 Progress Hook 【发布时间】:2010-01-08 15:22:50 【问题描述】:

我正在尝试使用 urllib2 http 客户端在 python 中创建下载进度条。我查看了 API(以及在 google 上),似乎 urllib2 不允许您注册进度挂钩。然而,旧的已弃用的 urllib 确实具有此功能。

有谁知道如何使用 urllib2 创建进度条或报告挂钩?还是有其他一些技巧可以获得类似的功能?

【问题讨论】:

【参考方案1】:

这是一个完全有效的示例,它建立在 Anurag 的响应分块方法之上。我的版本允许您设置块大小,并附加任意报告功能:

import urllib2, sys

def chunk_report(bytes_so_far, chunk_size, total_size):
   percent = float(bytes_so_far) / total_size
   percent = round(percent*100, 2)
   sys.stdout.write("Downloaded %d of %d bytes (%0.2f%%)\r" % 
       (bytes_so_far, total_size, percent))

   if bytes_so_far >= total_size:
      sys.stdout.write('\n')

def chunk_read(response, chunk_size=8192, report_hook=None):
   total_size = response.info().getheader('Content-Length').strip()
   total_size = int(total_size)
   bytes_so_far = 0

   while 1:
      chunk = response.read(chunk_size)
      bytes_so_far += len(chunk)

      if not chunk:
         break

      if report_hook:
         report_hook(bytes_so_far, chunk_size, total_size)

   return bytes_so_far

if __name__ == '__main__':
   response = urllib2.urlopen('http://www.ebay.com');
   chunk_read(response, report_hook=chunk_report)

【讨论】:

太好了,可以下载了。有类似的上传吗? (即写大量的帖子数据?) 这会将您的文件下载到哪里?我好像没找到。 @Zachary 据我所知,这不是“保存”文件;它正在打开一个网址。要保存文件,您将执行 file = open('myfile.html', 'wb') 然后 file.write(response.read()) 请注意,响应并不总是包含“Content-Length”标头。对于不支持它的服务器,这将失败。 @styfle:实际上,它正在打开一个 URL 并丢弃它的字节。 responde.read() 会破坏定期进度报告的全部意义。【参考方案2】:

为什么不直接读取数据块并在其间做任何你想做的事情,例如在线程中运行,挂钩到 UI 等

import urllib2

urlfile = urllib2.urlopen("http://www.google.com")

data_list = []
chunk = 4096
while 1:
    data = urlfile.read(chunk)
    if not data:
        print "done."
        break
    data_list.append(data)
    print "Read %s bytes"%len(data)

输出

Read 4096 bytes
Read 3113 bytes
done.

【讨论】:

唯一的是,我认为最后一行应该是 print "Read %s bytes"%len(data_list) @Zachary Brown ,不,因为我只是打印每次读取的数据量,虽然最好打印读取的总数据,但它仍然不会是 len(data_list)跨度> 【参考方案3】:

urlgrabber 内置了对进度通知的支持。

【讨论】:

【参考方案4】:

简化版:

temp_filename = "/tmp/" + file_url.split('/')[-1]
f = open(temp_filename, 'wb')
remote_file = urllib2.urlopen(file_url)

try:
    total_size = remote_file.info().getheader('Content-Length').strip()
    header = True
except AttributeError:
    header = False # a response doesn't always include the "Content-Length" header

if header:
    total_size = int(total_size)

bytes_so_far = 0

while True:
    buffer = remote_file.read(8192)
    if not buffer:
        sys.stdout.write('\n')
        break

    bytes_so_far += len(buffer)
    f.write(buffer)
    if not header:
        total_size = bytes_so_far # unknown size

    percent = float(bytes_so_far) / total_size
    percent = round(percent*100, 2)
    sys.stdout.write("Downloaded %d of %d bytes (%0.2f%%)\r" % (bytes_so_far, total_size, percent))

【讨论】:

【参考方案5】:

对 Triptych 的响应稍作修改以允许实际写出文件 (python3):

from urllib.request import urlopen

def chunk_report(bytes_so_far, chunk_size, total_size):
    percent = float(bytes_so_far) / total_size
    percent = round(percent*100, 2)
    sys.stdout.write("Downloaded %d of %d bytes (%0.2f%%)\r" %
                     (bytes_so_far, total_size, percent))

    if bytes_so_far >= total_size:
        sys.stdout.write('\n')


def chunk_read(response, chunk_size=8192, report_hook=None):
    total_size = response.info().get("Content-Length").strip()
    total_size = int(total_size)
    bytes_so_far = 0
    data = b""

    while 1:
        chunk = response.read(chunk_size)
        bytes_so_far += len(chunk)

        if not chunk:
            break

        if report_hook:
            report_hook(bytes_so_far, chunk_size, total_size)

        data += chunk

    return data

用法:

with open(out_path, "wb") as f:
    response = urlopen(filepath)
    data_read = chunk_read(response, report_hook=chunk_report)

    f.write(data_read)

【讨论】:

以上是关于Python urllib2 进度挂钩的主要内容,如果未能解决你的问题,请参考以下文章

Python2 urllib2用不了???求解。。。

python3.4没有 urllib2

python urllib 和 urllib2

Python:urllib 和urllib2之间的区别

python urllib2模块 在哪里下载?

python3中urllib2找不到怎么办