Я открываю файл с 100 000 URL. Мне нужно отправить HTTP-запрос на каждый URL и распечатать код состояния. Я использую Python 2.6 и до сих пор смотрел на многие запутанные способы, которыми Python реализует многопоточность / параллелизм. Я даже посмотрел на библиотеку Python Concurrence , но не могу понять, как правильно написать эту программу. Кто-нибудь сталкивался с подобной проблемой? Я думаю, что в целом мне нужно знать, как выполнить тысячи задач в Python как можно быстрее - я полагаю, это означает «одновременно».
python
http
concurrency
IgorGanapolsky
источник
источник
requests.get
иrequests.head
(т.е. запрос страницы против запроса головы) возвращать разные коды статуса, так что это не лучший советОтветы:
Twistedless решение:
Это немного быстрее, чем скрученное решение и использует меньше ресурсов процессора.
источник
concurrent*2
?conn.close()
. Открытие слишком большого количества http-соединений может в какой-то момент остановить ваш скрипт и съесть память.Queue
модуль был переименованqueue
в Python 3. Это код Python 2.Решение с использованием асинхронной сетевой библиотеки торнадо
источник
Все изменилось с 2010 года, когда он был опубликован, и я не пробовал все остальные ответы, но попробовал несколько, и я нашел, что это работает лучше всего для меня, используя python3.6.
Мне удалось получить около 150 уникальных доменов в секунду, работающих на AWS.
источник
time1 = time.time()
вверху цикла for иtime2 = time.time()
сразу после цикла for.Темы абсолютно не ответ здесь. Они обеспечат узкие места как процесса, так и ядра, а также ограничения пропускной способности, которые неприемлемы, если общая цель - «самый быстрый путь».
Немного
twisted
и его асинхронныйHTTP
клиент даст вам гораздо лучшие результаты.источник
Я знаю, что это старый вопрос, но в Python 3.7 вы можете сделать это, используя
asyncio
иaiohttp
.Вы можете прочитать больше об этом и увидеть пример здесь .
источник
urls= [fetch(construct_fetch_url(u),idx) for idx, u in enumerate(some_URI_list)]
results = await asyncio.gather(*urls)
Используйте grequests , это комбинация запросов + модуль Gevent.
GRequests позволяет использовать запросы с Gevent, чтобы легко выполнять асинхронные HTTP-запросы.
Использование простое:
Создайте набор неотправленных запросов:
Отправьте их все одновременно:
источник
Хороший подход к решению этой проблемы заключается в том, чтобы сначала написать код, необходимый для получения одного результата, а затем включить многопоточный код для распараллеливания приложения.
В идеальном мире это просто означало бы одновременный запуск 100 000 потоков, которые выводят свои результаты в словарь или список для последующей обработки, но на практике вы ограничены в количестве параллельных HTTP-запросов, которые вы можете выполнить таким способом. Локально, у вас есть ограничения на количество сокетов, которые вы можете открывать одновременно, сколько потоков исполнения допускает ваш интерпретатор Python. Удаленно, вы можете быть ограничены в количестве одновременных подключений, если все запросы направлены к одному серверу или ко многим. Эти ограничения, вероятно, потребуют от вас написания сценария таким образом, чтобы опрашивать только небольшую часть URL-адресов одновременно (100, как упоминалось в другом постере, вероятно, является приличным размером пула потоков, хотя вы можете обнаружить, что вы может успешно развернуть еще много).
Вы можете использовать этот шаблон проектирования для решения вышеуказанной проблемы:
list
илиdict
в CPython, вы можете безопасно добавлять или вставлять уникальные элементы из ваших потоков без блокировок , но если вы записываете в файл или требуете более сложного взаимодействия данных между потоками, вам следует использовать блокировка взаимного исключения для защиты этого государства от коррупции .Я хотел бы предложить вам использовать модуль потоков . Вы можете использовать его для запуска и отслеживания запущенных потоков. Поддержка потоков в Python отсутствует, но описание вашей проблемы предполагает, что ее вполне достаточно для ваших нужд.
И, наконец, если вы хотите , чтобы увидеть довольно просто приложение параллельного сетевого приложения , написанного в Python, проверить ssh.py . Это небольшая библиотека, которая использует потоки Python для распараллеливания многих SSH-соединений. Дизайн достаточно близок к вашим требованиям, поэтому вы можете найти его хорошим ресурсом.
источник
Если вы хотите добиться максимальной производительности, возможно, вы захотите использовать асинхронный ввод-вывод, а не потоки. Издержки, связанные с тысячами потоков ОС, нетривиальны, и переключение контекста в интерпретаторе Python добавляет еще больше. Работа с потоками, безусловно, сделает работу, но я подозреваю, что асинхронный маршрут обеспечит лучшую общую производительность.
В частности, я бы предложил асинхронный веб-клиент в библиотеке Twisted ( http://www.twistedmatrix.com ). У него, по общему признанию, крутая кривая обучения, но его довольно легко использовать, если вы хорошо разбираетесь в стиле асинхронного программирования Twisted.
Инструкции по использованию интерфейса асинхронного веб-клиента Twisted доступны по адресу:
http://twistedmatrix.com/documents/current/web/howto/client.html
источник
Решение:
Testtime:
Pingtime:
источник
Использование пула потоков - хороший вариант, и это будет довольно просто. К сожалению, в python нет стандартной библиотеки, которая делает пулы потоков очень простыми. Но вот достойная библиотека, с которой стоит начать: http://www.chrisarndt.de/projects/threadpool/
Пример кода с их сайта:
Надеюсь это поможет.
источник
q_size
> 0, размер очереди рабочих запросов ограничен, и пул потоков блокируется, когда очередь заполнена, и пытается добавить в нее больше рабочих запросов (см.putRequest
Метод), если только вы не используете положительноеtimeout
значение дляputRequest
».Создайте
epoll
объект,откройте множество клиентских TCP-сокетов,
настройте их буферы отправки так, чтобы они были немного больше заголовка запроса,
отправьте заголовок запроса - это должно быть немедленно, просто поместив в буфер, зарегистрируйте сокет в
epoll
объекте,сделайте
.poll
наepoll
объекте,прочитайте сначала 3 байты из каждого сокета from
.poll
,запишите их,
sys.stdout
затем\n
(не очищайте), закройте клиентский сокет.Ограничить количество открытых сокетов одновременно - обрабатывать ошибки при создании сокетов. Создайте новый сокет, только если другой закрыт.
Настройте пределы ОС.
Попробуйте разделить несколько (не много) процессов: это может помочь немного эффективнее использовать процессор.
источник
В вашем случае многопоточность, вероятно, сработает, поскольку вы, скорее всего, будете тратить большую часть времени на ожидание ответа. В стандартной библиотеке есть полезные модули, такие как Queue, которые могут помочь.
Раньше я делал аналогичные вещи с параллельной загрузкой файлов, и это было достаточно для меня, но не в том масштабе, о котором вы говорите.
Если ваша задача была более привязана к процессору, вы можете посмотреть на многопроцессорный модуль, который позволит вам использовать больше процессоров / ядер / потоков (больше процессов, которые не будут блокировать друг друга, поскольку блокировка выполняется для каждого процесса)
источник
Подумайте об использовании Windmill , хотя Windmill, вероятно, не может сделать столько потоков.
Вы можете сделать это с помощью сценария Python, запущенного вручную, на 5 машинах, каждая из которых соединяется с исходящими портами 40000-60000, открывая 100 000 соединений портов.
Кроме того, это может помочь выполнить пример теста с приложением QA с хорошими потоками, таким как OpenSTA , чтобы понять, сколько может обрабатывать каждый сервер.
Также попробуйте изучить использование простого Perl с классом LWP :: ConnCache. Таким образом, вы, вероятно, получите больше производительности (больше подключений).
источник
Этот скрученный асинхронный веб-клиент работает довольно быстро.
источник
Я обнаружил, что использование
tornado
пакета - самый быстрый и простой способ добиться этого:источник
Самый простой способ - использовать встроенную библиотеку потоков Python.
Они не являются "реальными" / потоками ядра.У них есть проблемы (например, сериализация), но они достаточно хороши. Вы хотите, чтобы очередь и пул потоков. Один вариант здесь , но это тривиально, чтобы написать свой собственный. Вы не можете распараллелить все 100 000 вызовов, но вы можете запустить 100 (или около того) из них одновременно.источник