我的任務是從給定的url列表下載1M +圖像。推薦的方式是什麼?使用gevent下載圖像
看完Greenlet Vs. Threads之後,我看了一下gevent
,但是我無法可靠地運行。我玩了100個網站的測試集,有時在1.5秒內完成,但有時需要超過30秒,這很奇怪,因爲每個請求的超時時間是0.1,所以它不應該超過10秒。
見下面的代碼
我也看了成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'類似的問題。還有人告訴我,'multiprocessing'不適合這種類型的任務:http://stackoverflow.com/a/27016937/380038 – Framester
有趣!我可以看到多處理效率/可擴展性不高,但我不明白爲什麼它不適用於適度的池大小(32倍)。希望你能得到一個很好的答案,因爲我想我也會學到一些東西! – foz