使用urllib3下载文件的最佳方法是什么

run*_*g.t 14 python download urllib3

我想通过HTTP协议下载文件urllib3.我已设法使用以下代码执行此操作:

 url = 'http://url_to_a_file'
 connection_pool = urllib3.PoolManager()
 resp = connection_pool.request('GET',url )
 f = open(filename, 'wb')
 f.write(resp.data)
 f.close()
 resp.release_conn()
Run Code Online (Sandbox Code Playgroud)

但我想知道这样做的正确方法是什么.例如,它适用于大文件,如果没有做什么,使这个代码更容易容忍和可扩展.

注意.对我来说,重要的是不要使用urllib3urllib2,因为我希望我的代码是线程安全的.

sha*_*zow 22

您的代码段已关闭.值得注意的两件事:

  1. 如果您正在使用resp.data,它将使用整个响应并返回连接(您不需要resp.release_conn()手动).如果你把数据保存在内存中很酷,这很好.

  2. 您可以使用resp.read(amt)哪个流将响应,但是需要通过连接返回连接resp.release_conn().

这看起来像......

import urllib3
http = urllib3.PoolManager()
r = http.request('GET', url, preload_content=False)

with open(path, 'wb') as out:
    while True:
        data = r.read(chunk_size)
        if not data:
            break
        out.write(data)

r.release_conn()
Run Code Online (Sandbox Code Playgroud)

在这种情况下,文档可能有点缺乏.如果有人有兴趣提出改进urllib3文档pull请求,那将非常感激.:)

  • 好问题。64kb 可能是一个安全的选择(2**16 或 65536)。 (2认同)
  • 当`for data in request.read(chunk_size)\n\tout.write(data)`*似乎*达到相同的结果时,是否有理由让`while`循环? (2认同)

Ale*_*ecz 8

最正确的方法可能是获取一个表示 HTTP 响应的类文件对象,并使用shutil.copyfileobj 将其复制到真实文件中,如下所示:

url = 'http://url_to_a_file'
c = urllib3.PoolManager()

with c.request('GET',url, preload_content=False) as resp, open(filename, 'wb') as out_file:
    shutil.copyfileobj(resp, out_file)

resp.release_conn()     # not 100% sure this is required though
Run Code Online (Sandbox Code Playgroud)

  • 需要使用 preload_content=False 执行 resp.release_conn() ,以便池管理器可以重用连接。请参阅[流媒体和 IO](https://urllib3.readthedocs.io/en/latest/advanced-usage.html#streaming-and-io)。 (2认同)