23

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

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

笔记。例如,使用urllib3库对我来说很重要,因为我希望我的代码是线程安全的。urllib2

4

3 回答 3

37

您的代码片段很接近。有两点值得注意:

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

  2. 您可以使用resp.read(amt)which 将流式传输响应,但连接需要通过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()

在这种情况下,文档可能有点缺乏。如果有人有兴趣提出拉取请求以改进 urllib3 文档,我们将不胜感激。:)

于 2013-06-24T22:03:46.377 回答
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
于 2014-12-10T16:50:52.780 回答
1

使用 urllib3 最简单​​的方法,您可以使用 shutil 自动管理包。

import urllib3
import shutil

http = urllib3.PoolManager()
with open(filename, 'wb') as out:
    r = http.request('GET', url, preload_content=False)
    shutil.copyfileobj(r, out)
于 2020-05-28T22:10:59.747 回答