ускорение urlib.urlretrieve

Я загружаю фотографии из Интернета, и, как оказалось, мне нужно загрузить много фотографий. Я использую версию следующего фрагмента кода (фактически перебираю ссылки, которые я собираюсь загрузить и загрузить изображения:

import urllib urllib.urlretrieve(link, filename) 

Я загружаю примерно 1000 снимков каждые 15 минут, что ужасно медленно в зависимости от количества фотографий, которые мне нужно скачать.

Для эффективности я устанавливал тайм-аут каждые 5 секунд (все еще много загрузок длится намного дольше):

 import socket socket.setdefaulttimeout(5) 

Помимо запуска задания на компьютерном кластере для параллелизации загрузки, есть ли способ сделать загрузку изображения быстрее / эффективнее?

2 Solutions collect form web for “ускорение urlib.urlretrieve”

мой код выше был очень наивным, поскольку я не использовал многопоточность. Очевидно, что для запросов URL-адресов требуется ответ, но нет причин, по которым компьютер не может отправлять дополнительные запросы, пока прокси-сервер отвечает.

Выполняя следующие настройки, вы можете повысить эффективность на 10x – и есть дополнительные способы повышения эффективности, с такими пакетами, как scrapy.

Чтобы добавить многопоточность, сделайте что-то вроде следующего, используя пакет многопроцессорности:

1) инкапсулировать поиск URL в функции:

 import import urllib.request def geturl(link,i): try: urllib.request.urlretrieve(link, str(i)+".jpg") except: pass 

2) затем создайте коллекцию со всеми URL-адресами, а также имена, которые вы хотите загрузить для загруженных изображений:

 urls = [url1,url2,url3,urln] names = [i for i in range(0,len(urls))] 

3) Импортируйте класс пула из пакета многопроцессорности и создайте объект с использованием такого класса (очевидно, вы включили бы все импорт в первую строку своего кода в реальной программе):

 from multiprocessing.dummy import Pool as ThreadPool pool = ThreadPool(100) 

затем используйте метод pool.starmap () и передайте функцию и аргументы функции.

 results = pool.starmap(geturl, zip(links, d)) 

note: pool.starmap () работает только в Python 3

Когда программа переходит к ожиданию ввода-вывода, выполнение приостанавливается, так что ядро ​​может выполнять операции низкого уровня, связанные с запросом ввода-вывода (это называется context switch) и не возобновляется до тех пор, пока операция ввода-вывода не будет завершено.

Контекстное переключение – довольно тяжелая операция. Это требует от нас сохранения состояния нашей программы (потери какого-либо кэширования у нас на уровне CPU) и отказа от использования процессора. Позже, когда нам разрешат снова работать, мы должны потратить время на повторную инициализацию нашей программы на материнской плате и подготовку к возобновлению (конечно, все это происходит за кулисами).

С concurrency, с другой стороны, мы обычно имеем дело под названием «цикл событий», который управляет тем, что запускается в нашей программе, и когда. По сути, цикл событий – это просто список функций, которые нужно запустить. Функция в верхней части списка запускается, затем следующая и т. Д.

Ниже приведен простой пример цикла событий:

 from Queue import Queue from functools import partial eventloop = None class EventLoop(Queue): def start(self): while True: function = self.get() function() def do_hello(): global eventloop print "Hello" eventloop.put(do_world) def do_world(): global eventloop print "world" eventloop.put(do_hello) if __name__ == "__main__": eventloop = EventLoop() eventloop.put(do_hello) eventloop.start() 

Если приведенное выше похоже на то, что вы можете использовать, и вы также хотели бы увидеть, как gevent, tornado, и AsyncIO, могут помочь в вашей проблеме, а затем отправиться в вашу (университетскую) библиотеку, посмотрите High Performance Python от Micha Gorelick и Ян Озсвальд , и читал стр. 181-202.

Примечание: выше код и текст из упомянутой книги .

Python - лучший язык программирования в мире.