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
ライブラリを使用することが重要です。
コードスニペットが閉じています。注目に値する2つのこと:
_resp.data
_を使用している場合は、応答全体を消費して接続を返します(手動でresp.release_conn()
する必要はありません)。これは、データをメモリ内に保持することに問題がない場合は問題ありません。
応答をストリーミングする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のドキュメントを改善するためのプルリクエスト を作成することに興味がある場合、それは大歓迎です。 :)
これを行う最も正しい方法は、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