как включить запросы в асинхронном режиме? - PullRequest
17 голосов
/ 29 февраля 2012

для этого кода:

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)

этот результат:

by requests: 18.3397213892 seconds
by urllib2: 2.48605842363 seconds

в сниффере это выглядит так:

описание: первые 5 запросов отправляются библиотекой запросов, следующие 5 запросов отправляются библиотекой urllib2. красный - время, когда работа была заморожена, темный - при получении данных ... wtf?!

Как это возможно, если библиотека сокетов пропатчена и библиотеки должны работать одинаково? Как использовать запросы без запросов .async для асинхронной работы?

Ответы [ 5 ]

15 голосов
/ 05 марта 2012

Извините, Кеннет Рейтц. Его библиотека замечательна.

Я тупой. Мне нужно выбрать патч обезьяны для httplib, как это:

gevent.monkey.patch_all(httplib=True)

Поскольку исправление для httplib по умолчанию отключено.

7 голосов
/ 02 марта 2012

Как указал Кеннет, еще одна вещь, которую мы можем сделать, - позволить модулю requests обрабатывать асинхронную часть. Я внес изменения в ваш код соответственно. Опять же, для меня результаты показывают, что модуль requests работает лучше, чем urllib2

Это означает, что мы не можем «потянуть» часть обратного вызова. Но это должно быть хорошо, потому что основной выигрыш следует ожидать только с HTTP-запросами из-за задержки запроса / ответа.

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)

Вот один из моих результатов:

by requests: 2.44117593765 seconds
by urllib2: 4.41298294067 seconds
5 голосов
/ 01 марта 2012

Requests имеет поддержку Gevent, интегрированную в кодовую базу:

http://docs.python -requests.org / о / последняя / пользователь / продвинутый / # асинхронных-запросы

2 голосов
/ 22 июня 2016

Из запросов документов Блокировка или неблокирование :

Если вас беспокоит использование блокировки ввода-вывода, существует множество проектов, в которых комбинируются запросы с одной из сред асинхронности Python. Два отличных примера: grequests и request-futures .

2 голосов
/ 01 марта 2012

Я запустил ваш код на моей машине (python 2.7.1, gevent 0.13.0, requests 0.10.6). Оказалось, что время всегда было на добрую секунду быстрее при использовании модуля запросов. Какие версии вы используете? Обновление может просто решить эту проблему для вас.

by requests: 3.7847161293 seconds
by urllib2: 4.92611193657 seconds

by requests: 2.90777993202 seconds
by urllib2: 7.99798607826 seconds
...