문제

이 코드의 경우 :

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?!

소켓 라이브러리 패치 및 라이브러리가 동일하게 작동 해야하는 경우 어떻게 해당되는지 어떻게 작동 하는가? 비동기 작업을위한 Requests.Async가없는 요청을 사용하는 방법은 무엇입니까?

도움이 되었습니까?

해결책

죄송합니다 Kenneth Reitz.그의 도서관은 훌륭합니다.

나는 어리 석다.다음과 같은 httplib에 대한 원숭이 패치를 선택해야합니다.

gevent.monkey.patch_all(httplib=True)
.

httplib의 패치가 기본적으로 비활성화되어 있기 때문에

다른 팁

kenneth가 지적했듯이, 우리가 할 수있는 또 다른 일은 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
.

요청은 코드베이스에 통합 된 GEVENT 지원이 있습니다.

http://docs.python-requests.org/en/latest/사용자 / 고급 / # 비동기 요청

i 컴퓨터에서 코드를 실행했습니다 (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
.

요청의 doc 차단 또는 비- 블로킹 :

io를 차단하는 데 염려하는 경우 파이썬의 비동기 프레임 워크 중 하나와 요청을 결합하는 많은 프로젝트가 많이 있습니다.두 가지 훌륭한 예제는 Grquests 요청 - 선물 .

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top