requests futures python python-requests gevent

python - futures - ¿De qué manera es grequests asincrónico?



asynchronous request python (3)

He estado usando la biblioteca de solicitudes de python durante algún tiempo, y recientemente tuve la necesidad de hacer una solicitud de forma asíncrona, lo que significa que me gustaría enviar la solicitud HTTP, hacer que mi hilo principal continúe ejecutándose y tener una devolución de llamada cuando el solicitar devoluciones.

Naturalmente, me llevaron a la biblioteca grequests ( https://github.com/kennethreitz/grequests ), pero estoy confundido sobre el comportamiento. Por ejemplo:

import grequests def print_res(res): from pprint import pprint pprint (vars(res)) req = grequests.get(''http://www.codehenge.net/blog'', hooks=dict(response=print_res)) res = grequests.map([req]) for i in range(10): print i

El código anterior producirá el siguiente resultado:

<...large HTTP response output...> 0 1 2 3 4 5 6 7 8 9

La llamada grequests.map () obviamente bloquea hasta que la respuesta HTTP esté disponible. Parece probable que malinterpreté el comportamiento ''asíncrono'' aquí, y la biblioteca grequests es solo para realizar múltiples solicitudes HTTP concurrentemente y enviar todas las respuestas a una única devolución de llamada. Es esto exacto?


Crea una lista de solicitudes y luego .imap con .imap :

event_list = [grequests.get(url_viol_card, params={"viol": i}, session=session) for i in print_ev_list] for r in grequests.imap(event_list, size=5): print(r.request.url)

  • session es requests.Session() objeto (opcional)
  • size=5 envía 5 solicitudes simultáneamente: tan pronto como se complete una de ellas, se envía la siguiente.
  • En este ejemplo, cuando se completa cualquier solicitud (desordenada) se imprime su url

Si no desea utilizar las grequests , puede implementar las solicitudes con devoluciones de llamadas utilizando las requests + el módulo de threading de la biblioteca estándar. En realidad es muy fácil, y si lo único que quieres hacer es enviar solicitudes con devoluciones de llamadas, la API es más bonita que la proporcionada por las grequests .

from threading import Thread from requests import get, post, put, patch, delete, options, head request_methods = { ''get'': get, ''post'': post, ''put'': put, ''patch'': patch, ''delete'': delete, ''options'': options, ''head'': head, } def async_request(method, *args, callback=None, timeout=15, **kwargs): """Makes request on a different thread, and optionally passes response to a `callback` function when request returns. """ method = request_methods[method.lower()] if callback: def callback_with_args(response, *args, **kwargs): callback(response) kwargs[''hooks''] = {''response'': callback_with_args} kwargs[''timeout''] = timeout thread = Thread(target=method, args=args, kwargs=kwargs) thread.start()

Puede verificar que funciona como una llamada AJAX en JS: envía una solicitud en otro hilo, hace algunas cosas en el hilo principal, y cuando la solicitud regresa, invoca una devolución de llamada. Esta devolución de llamada solo imprime el contenido de la respuesta.

async_request(''get'', ''http://httpbin.org/anything'', callback=lambda r: print(r.json())) for i in range(10): print(i)


.map() está destinado a ejecutar la recuperación de varias URL en paralelo, y de hecho esperará a que se completen estas tareas (se gevent.joinall(jobs) ).

Utilice .send() lugar para generar trabajos, utilizando una instancia de Pool :

req = grequests.get(''http://www.codehenge.net/blog'', hooks=dict(response=print_res)) job = grequests.send(req, grequests.Pool(1)) for i in range(10): print i

Sin el grupo, la llamada .send() bloqueará aún, pero solo para la llamada gevent.spawn() que ejecuta.