asyncio.gather con return_exceptions=True coloca las excepciones de las tareas en su lista de resultados. Por tanto, esperar el lote sin excepción no significa que todas las solicitudes de proxy hayan tenido éxito.

Mantenga el destino y el proxy elegido junto a los awaitables enviados y, después, inspeccione cada resultado:

outcomes = await asyncio.gather(*jobs, return_exceptions=True)

for (url, proxy), outcome in zip(routes, outcomes):
    if isinstance(outcome, BaseException):
        record_failure(url, proxy, outcome)
    else:
        record_success(url, proxy, outcome)

jobs contiene las corrutinas de solicitud de la aplicación; routes contiene sus pares (url, proxy) correspondientes en el mismo orden. Las funciones de registro son el tratamiento de resultados propio de la aplicación. gather conserva el orden de entrada aunque el orden de finalización sea distinto.

Clasifique un CancelledError devuelto por una tarea hija como cancelación en lugar de culpar a su proxy. La cancelación del gather externo sigue propagándose a las hijas inacabadas; return_exceptions no convierte esa cancelación en un éxito ordinario.

El tratamiento del estado HTTP también corresponde dentro de la operación de solicitud. aiohttp no lanza una excepción por cada error HTTP de forma predeterminada, así que devuelva el estado o aplique raise_for_status según la política de la tarea.

Una vez visibles los resultados, la aplicación puede distinguir los fallos de conexión de las respuestas del destino y decidir qué trabajo merece otro intento.

Artículos relacionados