¿Cómo podría usar las solicitudes en asyncio?

Quiero hacer tareas de solicitud http paralelas en asyncio , pero encuentro que python-requests bloquearían el bucle de asyncio de asyncio . He encontrado aiohttp pero no pudo proporcionar el servicio de solicitud http utilizando un proxy http.

Así que quiero saber si hay una manera de hacer solicitudes http asíncronas con la ayuda de asyncio .

Para usar solicitudes (o cualquier otra biblioteca de locking) con asyncio, puede usar BaseEventLoop.run_in_executor para ejecutar una función en otro subproceso y obtener de ella el resultado. Por ejemplo:

 import asyncio import requests @asyncio.coroutine def main(): loop = asyncio.get_event_loop() future1 = loop.run_in_executor(None, requests.get, 'http://www.google.com') future2 = loop.run_in_executor(None, requests.get, 'http://www.google.co.uk') response1 = yield from future1 response2 = yield from future2 print(response1.text) print(response2.text) loop = asyncio.get_event_loop() loop.run_until_complete(main()) 

Esto obtendrá ambas respuestas en paralelo.

Con Python 3.5 puede usar la nueva syntax async / async :

 import asyncio import requests async def main(): loop = asyncio.get_event_loop() future1 = loop.run_in_executor(None, requests.get, 'http://www.google.com') future2 = loop.run_in_executor(None, requests.get, 'http://www.google.co.uk') response1 = await future1 response2 = await future2 print(response1.text) print(response2.text) loop = asyncio.get_event_loop() loop.run_until_complete(main()) 

Ver PEP0492 para más.

aiohttp se puede usar con el proxy HTTP ya:

 import asyncio import aiohttp @asyncio.coroutine def do_request(): proxy_url = 'http://localhost:8118' # your proxy address response = yield from aiohttp.request( 'GET', 'http://google.com', proxy=proxy_url, ) return response loop = asyncio.get_event_loop() loop.run_until_complete(do_request()) 

Las respuestas anteriores siguen utilizando las antiguas guías de estilo Python 3.4. Esto es lo que escribirías si obtuvieras Python 3.5+.

aiohttp soporta HTTP proxy ahora

 import aiohttp import asyncio async def fetch(session, url): async with session.get(url) as response: return await response.text() async def main(): urls = [ 'http://python.org', 'https://google.com', 'http://yifei.me' ] tasks = [] async with aiohttp.ClientSession() as session: for url in urls: tasks.append(fetch(session, url)) htmls = await asyncio.gather(*tasks) for html in htmls: print(html[:100]) if __name__ == '__main__': loop = asyncio.get_event_loop() loop.run_until_complete(main()) 

Las solicitudes actualmente no son compatibles con asyncio y no hay planes para proporcionar dicho soporte. Es probable que pueda implementar un “Adaptador de transporte” personalizado (como se explica aquí ) que sepa cómo usar asyncio .

Si me encuentro con algún tiempo, es algo que realmente podría analizar, pero no puedo prometer nada.

Hay un buen caso de subprocesos y subprocesos asíncronos / await en un artículo de Pimin Konstantin Kefaloukos Solicitudes HTTP paralelas sencillas con Python y asyncio :

Para minimizar el tiempo total de finalización, podríamos boost el tamaño del grupo de hilos para que coincida con el número de solicitudes que tenemos que hacer. Afortunadamente, esto es fácil de hacer, como veremos a continuación. El código que se muestra a continuación es un ejemplo de cómo realizar veinte solicitudes HTTP asíncronas con un grupo de subprocesos de veinte subprocesos de trabajo:

 # Example 3: asynchronous requests with larger thread pool import asyncio import concurrent.futures import requests async def main(): with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor: loop = asyncio.get_event_loop() futures = [ loop.run_in_executor( executor, requests.get, 'http://example.org/' ) for i in range(20) ] for response in await asyncio.gather(*futures): pass loop = asyncio.get_event_loop() loop.run_until_complete(main())