2013-06-24 13 views
6

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

をしかし、私はこれを行うための適切な方法であると思いまして。 たとえば、大きなファイルに対してはうまくいくでしょうし、このコードをバグに強く、スケーラブルにするために何をすればいいのかわかりません。

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

答えて

14

コードスニペットが閉じています。注目に値する二つのこと:あなたがresp.dataを使用している場合

  1. 、それは全体の応答を消費し、(手動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() 

ドキュメントでは、ビットは、このシナリオに欠けているかもしれません。誰もがpull-request to improve the urllib3 documentationを作ることに興味があるなら、それは非常に高く評価されるでしょう。あなたがこれを行うには、最も正しい方法は、HTTPレスポンスを表すファイルのようなオブジェクトを取得するにはおそらく完全なコンテンツ

http.request('GET', url, preload_content=False) 
+0

ご回答ありがとうございます。 –

+0

もう1つ質問です。 'r = http.request( 'POST'、url)'を追加すると、POSTメソッドで動作しますか? –

+0

@ running.tエラー、私のコードで間違いでした。あなたが正しいです、メソッドが最初に行く必要があり、あなたのスニペットが動作します。 (私の答えを更新しました) – shazow

-2

追加以下のように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 
+0

@ 2Dee:何が間違っているか教えてください。私は自分自身を修正することができます。 – giridhar

+1

あなたの答えは正しいかもしれませんが(私はurllib3に精通していません)、それは完全に質問された問題に対処できないようです。私はあなたの答えを投票しませんでした、私の名前が投稿の下に表示されている場合は、私はコードが正しくフォーマットされるようにあなたの答えを編集したためです。これがあなたのために明確になったことを願っています;) – 2Dee

2

をダウンロードし終わると、それをコピーする他の変数preload_contentという名前:)

関連する問題