python multithreading asynchronous python-requests gevent

Peticiones de Python con multiproceso.



multithreading asynchronous (1)

Instale el módulo grequests que funciona con gevent (las requests no están diseñadas para async):

pip install grequests

Luego cambia el código a algo como esto:

import grequests class Test: def __init__(self): self.urls = [ ''http://www.example.com'', ''http://www.google.com'', ''http://www.yahoo.com'', ''http://www.stackoverflow.com/'', ''http://www.reddit.com/'' ] def exception(self, request, exception): print "Problem: {}: {}".format(request.url, exception) def async(self): results = grequests.map((grequests.get(u) for u in self.urls), exception_handler=self.exception, size=5) print results test = Test() test.async()

Esto es oficialmente recomendado por el proyecto de requests :

¿Bloqueo o no bloqueo?

Con el adaptador de transporte predeterminado en su lugar, las solicitudes no proporcionan ningún tipo de E / S sin bloqueo. La propiedad Response.content se bloqueará hasta que se haya descargado la respuesta completa. Si necesita más granularidad, las funciones de transmisión de la biblioteca (consulte Solicitudes de transmisión por secuencias) le permiten recuperar cantidades más pequeñas de la respuesta a la vez. Sin embargo, estas llamadas seguirán bloqueando.

Si le preocupa el uso del bloqueo de E / S, hay muchos proyectos que combinan Solicitudes con uno de los marcos de trabajo asíncrónicos de Python. Dos ejemplos excelentes son las requests-futures grequests y las requests-futures grequests .

El uso de este método me da un notable aumento de rendimiento con 10 URL: 0.877s frente a 3.852s con su método original.

He estado tratando de construir un raspador con funcionalidad de multihilo en los últimos dos días. De alguna manera todavía no podía manejarlo. Al principio intenté un enfoque de subprocesos múltiples con el módulo de subprocesamiento, pero no fue más rápido que usar un solo subproceso. Más tarde, supe que las solicitudes están bloqueando y el enfoque de subprocesamiento múltiple no está funcionando. Así que seguí investigando y descubrí las misiones y gevent. Ahora estoy ejecutando pruebas con gevent y todavía no es más rápido que usar un solo hilo. ¿Está mal mi codificación?

Aquí está la parte relevante de mi clase:

import gevent.monkey from gevent.pool import Pool import requests gevent.monkey.patch_all() class Test: def __init__(self): self.session = requests.Session() self.pool = Pool(20) self.urls = [...urls...] def fetch(self, url): try: response = self.session.get(url, headers=self.headers) except: self.logger.error(''Problem: '', id, exc_info=True) self.doSomething(response) def async(self): for url in self.urls: self.pool.spawn( self.fetch, url ) self.pool.join() test = Test() test.async()