2012-02-29 13 views
16

per questo codice:come abilitare la modalità async delle richieste?

import sys 

import gevent 
from gevent import monkey 

monkey.patch_all() 

import requests 
import urllib2 

def worker(url, use_urllib2=False): 
    if use_urllib2: 
     content = urllib2.urlopen(url).read().lower() 
    else: 
     content = requests.get(url, prefetch=True).content.lower() 
    title = content.split('<title>')[1].split('</title>')[0].strip() 

urls = ['http://www.mail.ru']*5 

def by_requests(): 
    jobs = [gevent.spawn(worker, url) for url in urls] 
    gevent.joinall(jobs) 

def by_urllib2(): 
    jobs = [gevent.spawn(worker, url, True) for url in urls] 
    gevent.joinall(jobs) 

if __name__=='__main__': 
    from timeit import Timer 
    t = Timer(stmt="by_requests()", setup="from __main__ import by_requests") 
    print 'by requests: %s seconds'%t.timeit(number=3) 
    t = Timer(stmt="by_urllib2()", setup="from __main__ import by_urllib2") 
    print 'by urllib2: %s seconds'%t.timeit(number=3) 
    sys.exit(0) 

questo risultato:

by requests: 18.3397213892 seconds 
by urllib2: 2.48605842363 seconds 

in sniffer sembra questo:

Descrizione: primi 5 richieste sono sended dalla libreria richieste, prossimi 5 richieste sono inviato dalla libreria urllib2. rosso - è il momento in cui il lavoro è stato congelato, scuro - quando i dati ricevono ... wtf ?!

Come è possibile se la libreria di socket è corrotta e le librerie devono funzionare in modo identico? Come utilizzare le richieste senza request.async per lavoro asincrono?

+0

puoi spiegare il problema un po 'più? Perché non vuoi usare il modulo requests.async? – Phani

+0

Le richieste non funzionano in modo asincrono. Perché? Non voglio usare request.async perché contiene un'interfaccia cattiva da usare e non funziona anche asincronamente. Guarda l'immagine, è visibile la richiesta di lavoro e urllib2. – user1239798

+1

Vedere http://stackoverflow.com/questions/9110593/asynchronous-requests-with-python-requests e https://github.com/kennethreitz/grequests. –

risposta

14

spiacenti Kenneth Reitz. La sua biblioteca è meravigliosa.

Sono stupido. Ho bisogno di selezionare patch scimmia per httplib come questo:

gevent.monkey.patch_all(httplib=True) 

Perché la patch per httplib è disabilitata per impostazione predefinita.

+11

Non valido più: ValueError: gevent.httplib non è più fornito, httplib deve essere False – mamcx

+1

Usa grequests (di @KennethReitz). Sovrascrive principalmente i verbi principali ed eredita il resto. –

2

Ho eseguito il codice sulla mia macchina (python 2.7.1, gevent 0.13.0, requests 0.10.6). Si è scoperto che il tempo era sempre un buon secondo o due più veloce quando si utilizzava il modulo delle richieste. Quali versioni stai usando? Un aggiornamento potrebbe semplicemente risolvere il problema per te.

by requests: 3.7847161293 seconds 
by urllib2: 4.92611193657 seconds 

by requests: 2.90777993202 seconds 
by urllib2: 7.99798607826 seconds 
+0

Sto usando questa versione: python 2.7.2.5, gevent 0.13.6, richieste 0.10.6 – user1239798

+0

Le tue versioni sono ancora più avanzate, quindi è davvero strano. Ho pubblicato un'altra risposta, che potrebbe aiutarti. – Phani

7

Come ricordato da Kenneth, un'altra cosa che possiamo fare è lasciare che il modulo requests gestiscono la parte asincrona. Ho apportato modifiche al tuo codice di conseguenza. Ancora una volta, per me, i risultati mostrano costantemente che il modulo requests ha prestazioni migliori di

Ciò significa che non possiamo "collegare" la parte di richiamo. Ma dovrebbe andar bene, perché il guadagno maggiore dovrebbe essere previsto solo con le richieste HTTP a causa del ritardo richiesta/risposta.

import sys 

import gevent 
from gevent import monkey 

monkey.patch_all() 

import requests 
from requests import async 
import urllib2 

def call_back(resp): 
    content = resp.content 
    title = content.split('<title>')[1].split('</title>')[0].strip() 
    return title 

def worker(url, use_urllib2=False): 
    if use_urllib2: 
     content = urllib2.urlopen(url).read().lower() 
     title = content.split('<title>')[1].split('</title>')[0].strip() 

    else: 
     rs = [async.get(u) for u in url] 
     resps = async.map(rs) 
     for resp in resps: 
      call_back(resp) 

urls = ['http://www.mail.ru']*5 

def by_requests(): 
    worker(urls) 
def by_urllib2(): 
    jobs = [gevent.spawn(worker, url, True) for url in urls] 
    gevent.joinall(jobs) 

if __name__=='__main__': 
    from timeit import Timer 
    t = Timer(stmt="by_requests()", setup="from __main__ import by_requests") 
    print 'by requests: %s seconds'%t.timeit(number=3) 
    t = Timer(stmt="by_urllib2()", setup="from __main__ import by_urllib2") 
    print 'by urllib2: %s seconds'%t.timeit(number=3) 
    sys.exit(0) 

Ecco uno dei miei risultati:

by requests: 2.44117593765 seconds 
by urllib2: 4.41298294067 seconds 
+0

Ciao! Grazie per l'interesse per il mio problema. Ho eseguito il tuo codice e ho aggiornato l'immagine del primo post per mostrare come funziona il tuo codice. – user1239798

+0

Questo è il risultato del lavoro: per richieste: 25.532893147 secondi da urllib2: 9.65230888283 secondi – user1239798

+0

Ho paura di non poter replicare il tuo problema. Ho aggiornato gevent a 0.13.6 e l'ho provato su due macchine diverse. Ma il modulo 'requests' funzionava in modo asincrono. Cordiali saluti, l'ho provato su Ubuntu 11.04 e 11.10. – Phani

Problemi correlati