Question

pour ce code:

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)

Ce résultat:

by requests: 18.3397213892 seconds
by urllib2: 2.48605842363 seconds

En renifleur, il semble ceci:

Description: Les 5 premières demandes sont envoyées par la bibliothèque des demandes, les 5 demandes suivantes sont envoyées par la bibliothèque Urllib2. Rouge - Le travail est-il lyophilisé, sombre - quand les données reçoivent ... WTF ?!

Comment est-il possible si la bibliothèque de socket patchée et que les bibliothèques doivent fonctionner de manière identique? Comment utiliser les demandes sans demandes. Async pour un travail asynchronie?

Était-ce utile?

La solution

Désolé Kenneth Reitz. Sa bibliothèque est merveilleuse.

Je suis stupide. J'ai besoin de sélectionner le patch de singe pour httplib comme ceci:

gevent.monkey.patch_all(httplib=True)

Parce que le patch pour HTTPLIB est désactivé par défaut.

Autres conseils

Comme l'ont souligné Kenneth, une autre chose que nous pouvons faire est de laisser le requests Gandage du module La partie asynchrone. J'ai apporté des modifications à votre code en conséquence. Encore une fois, pour moi, les résultats montrent constamment que requests le module fonctionne mieux que urllib2

Cela signifie que nous ne pouvons pas "enfiler" la partie de rappel. Mais cela devrait être correct, car le gain majeur ne doit être attendu qu'avec les demandes HTTP en raison du retard de demande / réponse.

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)

Voici un de mes résultats:

by requests: 2.44117593765 seconds
by urllib2: 4.41298294067 seconds

Les demandes ont une prise en charge de gevent intégrée dans la base de code:

http://docs.python-requests.org/en/latest/user/advanced/#asynchronous-requests

J'ai dirigé votre code sur ma machine (python 2.7.1, gevent 0.13.0, requests 0.10.6). Il s'est avéré que le temps était toujours un bon deuxième ou deux plus rapidement lors de l'utilisation du module Demandes. Quelles versions utilisez-vous? Une mise à niveau peut simplement résoudre le problème pour vous.

by requests: 3.7847161293 seconds
by urllib2: 4.92611193657 seconds

by requests: 2.90777993202 seconds
by urllib2: 7.99798607826 seconds

À partir des demandes de doc Blocage ou non bloquant:

Si vous êtes préoccupé par l'utilisation du blocage d'IO, il existe de nombreux projets qui combinent des demandes avec l'un des cadres d'asynchronicité de Python. Deux excellents exemples sont grise et demandes-futures.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top