私の仕事は、指定されたURLリストから1M以上の画像をダウンロードすることです。そうするための推奨される方法は何ですか?geventで画像をダウンロードする
Greenlet Vs. Threadsを読んだ後、私はgevent
を調べましたが、確実に実行することができません。私は100個のURLのテストセットで遊んでいましたが、1.5秒で終了することもありましたが、リクエストごとのタイムアウト*が0.1であるので奇妙な30秒以上かかることがあります。
*コード
に以下を参照してください、私はまたgrequests
に見えたが、彼らはissues with exception handling.
私の要件は、「私は
- は(タイムアウトのダウンロード中に発生するエラーを調べることができます持っているようです、壊れた画像...)、
- 処理された画像の数の進行を監視し、
- はできるだけ速い。
from gevent import monkey; monkey.patch_all()
from time import time
import requests
from PIL import Image
import cStringIO
import gevent.hub
POOL_SIZE = 300
def download_image_wrapper(task):
return download_image(task[0], task[1])
def download_image(image_url, download_path):
raw_binary_request = requests.get(image_url, timeout=0.1).content
image = Image.open(cStringIO.StringIO(raw_binary_request))
image.save(download_path)
def download_images_gevent_spawn(list_of_image_urls, base_folder):
download_paths = ['/'.join([base_folder, url.split('/')[-1]])
for url in list_of_image_urls]
parameters = [[image_url, download_path] for image_url, download_path in
zip(list_of_image_urls, download_paths)]
tasks = [gevent.spawn(download_image_wrapper, parameter_tuple) for parameter_tuple in parameters]
for task in tasks:
try:
task.get()
except Exception:
print 'x',
continue
print '.',
test_urls = # list of 100 urls
t1 = time()
download_images_gevent_spawn(test_urls, 'download_temp')
print time() - t1
スレッドを使用する必要がありますか?代わりに複数のプロセスを使用できる場合は、 'multiprocessing.Pool'でこれを行うことができます。私は 'pool.map(download_image、url_list)'と 'pool.join()'を使って同様のことをします。 – foz
@foz、ありがとうございますが、同様の問題で 'multiprocessing.Pool'も試みました。また、私は、 'マルチプロセッシング 'はそのような種類のタスクのための適切なツールではないと言われました:http://stackoverflow.com/a/27016937/380038 – Framester
興味深い!私は、マルチプロセッシングが効率的でスケーラブルではないことを知ることができますが、私はそれが控えめなプールサイズ(あなたが持っていたように32)で動作してはならない理由を見ません。私はあなたも何かを学ぶと思うようにこれに良い答えを得ることを願っています! – foz