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
esrequests.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.