Збирати кожен результат із паралельних проксі-запитів urllib3
Спільно використовуйте налаштований ProxyManager між робочими потоками, споживайте ітератор результатів виконавця та відрізняйте утримання пулу від ліміту з'єднань.
Створення пулу робітників не передає викликачу завантажені сторінки. Зберігайте та споживайте значення, які повертає надіслана робота:
from concurrent.futures import ThreadPoolExecutor
import urllib3
manager = urllib3.ProxyManager(
'http://proxy.example:8080',
maxsize=4,
block=True,
)
def fetch(url):
response = manager.request(
'GET', url, timeout=urllib3.Timeout(connect=5, read=15),
)
return url, response.status, response.data
try:
with ThreadPoolExecutor(max_workers=4) as workers:
results = list(workers.map(fetch, urls))
finally:
manager.clear()Цей фрагмент припускає обмежений список URL і звичайні розміри відповідей. Для дозволених перевірок публічних URL без проксі-автентифікації кандидат зі списку HTTP-проксі може замінити прикладну HTTP-точку входу менеджера. Кожен результат містить свій URL, щоб викликач міг пов'язати статус і тіло з правильним запитом. map повертає результати в порядку введення; виняток у робітнику виникає, коли цей результат отримують.
Налаштований ProxyManager володіє пулом з'єднань для запитів. З використовуваним тут режимом попередньо завантаженої відповіді за замовчуванням urllib3 читає тіло й повертає з'єднання до свого пулу. Потоковій версії знадобилося б явне споживання та звільнення з'єднання.
maxsize зазвичай керує збереженими повторно використовуваними з'єднаннями, а не жорстким обмеженням на кожен відкритий сокет. block=True змінює відповідну поведінку пулу, щоб викликачі чекали на вільне з'єднання, а не відкривали додаткові понад ліміт цього пулу.
Кількість робітників обмежує одночасні виклики в цьому прикладі. За багатьох призначень також важливі схема пулу й маршрут для тунелів HTTPS; налаштування одного пулу не слід описувати як єдину глобальну квоту сокетів для кожного хоста.