web-dev-qa-db-ja.com

urllib3を使用してファイルをダウンロードする最良の方法は何ですか

urllib3を使用して、HTTPプロトコル経由でファイルをダウンロードしたいのですが。私はこれを次のコードを使用してなんとかしました:

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

しかし、これを行うにはproper方法とは何なのかと思っていました。たとえば、それは大きなファイルでうまく機能し、このコードをよりバグに強く、スケーラブルにするために何をすべきかはわかりません。

注意。たとえば、コードをスレッドセーフにするため、urllib3ではなくurllib2ライブラリを使用することが重要です。

16
running.t

コードスニペットが閉じています。注目に値する2つのこと:

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

このシナリオでは、ドキュメントが少し不足している可能性があります。誰かが rllib3のドキュメントを改善するためのプルリクエスト を作成することに興味がある場合、それは大歓迎です。 :)

24
shazow

これを行う最も正しい方法は、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
5
Alecz