Posteriormente a observar en diferentes repositorios y sitios webs al terminar nos encontramos con la solución que te compartiremos aquí.
Solución:
Nota
La siguiente respuesta es no aplicable a solicitudes v0.13.0+. La funcionalidad asíncrona se trasladó a grequests después de escribir esta pregunta. Sin embargo, podría simplemente reemplazar requests
con grequests
a continuación y debería funcionar.
Dejé esta respuesta tal como está para reflejar la pregunta original sobre el uso de solicitudes < v0.13.0.
Para hacer varias tareas con async.map
asincrónicamente tienes que:
- Define una función para lo que quieres hacer con cada objeto (tu tarea)
- Agregue esa función como un gancho de evento en su solicitud
- Llamar
async.map
en una lista de todas las solicitudes / acciones
Ejemplo:
from requests import async
# If using requests > v0.13.0, use
# from grequests import async
urls = [
'http://python-requests.org',
'http://httpbin.org',
'http://python-guide.org',
'http://kennethreitz.com'
]
# A simple task to do to each response object
def do_something(response):
print response.url
# A list to hold our things to do via async
async_list = []
for u in urls:
# The "hooks = {..." part is where you define what you want to do
#
# Note the lack of parentheses following do_something, this is
# because the response will be used as the first argument automatically
action_item = async.get(u, hooks = 'response' : do_something)
# Add the task to our list of things to do via async
async_list.append(action_item)
# Do our list of things to do via async
async.map(async_list)
async
ahora es un módulo independiente: grequests
.
Ver aquí: https://github.com/kennethreitz/grequests
Y allí: ¿Método ideal para enviar múltiples solicitudes HTTP a través de Python?
instalación:
$ pip install grequests
uso:
construir una pila:
import grequests
urls = [
'http://www.heroku.com',
'http://tablib.org',
'http://httpbin.org',
'http://python-requests.org',
'http://kennethreitz.com'
]
rs = (grequests.get(u) for u in urls)
enviar la pila
grequests.map(rs)
el resultado parece
[, , , , ]
grequests no parece establecer una limitación para las solicitudes simultáneas, es decir, cuando se envían varias solicitudes al mismo servidor.
Probé ambas solicitudes, futuros y grequests. Grequests es más rápido pero trae parches mono y problemas adicionales con las dependencias. request-futures es varias veces más lento que grequests. Decidí escribir las mías y simplemente envolví las solicitudes en ThreadPoolExecutor y fue casi tan rápido como las solicitudes grequest, pero sin dependencias externas.
import requests
import concurrent.futures
def get_urls():
return ["url1","url2"]
def load_url(url, timeout):
return requests.get(url, timeout = timeout)
with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
future_to_url = executor.submit(load_url, url, 10): url for url in get_urls()
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
try:
data = future.result()
except Exception as exc:
resp_err = resp_err + 1
else:
resp_ok = resp_ok + 1