Criar um pool de trabalhadores não entrega ao chamador as páginas transferidas. Guarde e consuma os valores devolvidos pelo trabalho submetido:

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()

Este fragmento pressupõe uma lista limitada de URLs e tamanhos de resposta comuns. Para verificações de URLs públicas permitidas sem autenticação de proxy, um candidato da lista de proxies HTTP pode substituir o endpoint HTTP de exemplo do gestor. Cada resultado inclui o seu URL para que o chamador possa associar o estado e o corpo ao pedido correto. map devolve os resultados pela ordem de entrada; uma exceção num trabalhador é levantada quando esse resultado é obtido.

O ProxyManager configurado possui a agregação de ligações para os pedidos. Com o modo de resposta pré-carregada predefinido usado aqui, o urllib3 lê o corpo e devolve a ligação ao seu pool. Uma versão em streaming exigiria consumo explícito e libertação da ligação.

maxsize normalmente controla as ligações reutilizáveis retidas, não um limite rígido em cada socket aberto. block=True altera o comportamento relevante do pool para que os chamadores esperem por uma ligação livre em vez de abrirem outras acima do limite desse pool.

O número de trabalhadores limita as chamadas concorrentes neste exemplo. Com muitos destinos, também importam a disposição do pool e a rota usada para os túneis HTTPS; uma definição por pool não deve ser descrita como uma quota global de sockets para cada anfitrião.

Artigos relacionados